sed:替换特定关键字后面的下一个单词

sed: replace immediate next word coming after a particular keyword

提问人:Ali J. Ghandour 提问时间:10/19/2023 最后编辑:Ali J. Ghandour 更新时间:10/21/2023 访问量:114

问:

在 GitHub 操作中,将推送请求合并到 main 时,我想将笔记本中出现的分支名称替换为 .main

例如,给定以下行:git clone --branch fork1 https://somrepo.git

使用下面的正则表达式,直到行尾的所有值都被替换,但是,我的意图是简单地替换为:fork1main

sed -i 's/\(--branch\)\(.*\)/\1 main/'

另一个例子,给出下面的行:"https://colab.research.google.com/github/user/repo/blob/fork2/notebook.ipynb"

使用下面的正则表达式,直到行尾的所有值都被替换,但是,我的意图是简单地替换为:fork2/main/

sed -i 's/\(blob\/\)\(.*\)/\1 main\//'

编辑:

为了澄清我的问题,我的 github 操作用例是在合并 PR 后将分支名称替换为多个文件。不,在这种情况下不起作用,因为ref_name将指向合并分支,而不是创建 PR 的初始分支。mainGITHUB_REF_NAME

name: Update Branch Name

    on:
      push:
        branches:
          - main
    
    jobs:
      restore_main_branch_name:
        runs-on: ubuntu-latest
        
        steps:
        - name: Checkout code
          uses: actions/checkout@v4
          
        - name: Update .ipynb files
          run: |
            sed -i "s|${{ github.ref_name }}|main|g" colabLaunchScript.ipynb
    
            
        - name: Commit changes
          run: |
            git config --local user.email "[email protected]"
            git config --local user.name "GitHub Actions"
            git commit -am "Restore main branch name in .ipynb file"
            git push -u origin main
正则表达式 sed github-actions 命令行界面

评论

2赞 tripleee 10/19/2023
看起来你想要的,而不是在第一种情况下,也许只是在第二种情况下。[^ ]*.*s%/fork1/%/main/%
1赞 tripleee 10/19/2023
在你确切地知道你在做什么之前,可能不会使用。-i
0赞 Wiktor Stribiżew 10/19/2023
对不起,不是复制品。
0赞 tripleee 10/19/2023
@WiktorStribiżew 您的链接显示的模式与 OP 在他们的问题中不同(但要好得多)。
0赞 Wiktor Stribiżew 10/19/2023
@tripleee 这是唯一的展示方式。如果我们要求替换输入字符串中没有,我们不能指望得到修改后的字符串。提供的输入中没有。因此,1)要么是用户打错了字,要么是2)用户没有向我们展示他们真正使用的东西。因此,我的示例表明,如果要搜索的字符串实际上位于输入内部,则没有问题。并且有效地表明这个问题是题外话。aafork1/

答:

1赞 Jay 10/19/2023 #1

第一种情况:匹配空格,后跟一系列非空格。将非空格替换为main

s/\(--branch\)\s\+\(\S\+\)/\1 main/

正如用户 tripleee 所指出的,您的 sed 版本可能不支持。或者,您可以使用:\s\S

s/\(--branch\)[[:space:]]\+\([^[:space:]]\+\)/\1 main/

第二种情况:改为:/fork1//main/

s#/fork1/#/main/#

注意:在这种情况下,选择的替换分隔符是通常首选的,因此不必对其进行转义。#//

评论

2赞 tripleee 10/19/2023
Perl 速记 like 和 not portable;它们在某些 S 中起作用,但在其他 S 中不起作用。\s\Ssed
0赞 Jay 10/19/2023
@tripleee 公平,谢谢。我添加了一个替代版本,它代替了[:space:]
0赞 tripleee 10/21/2023 #2

要替换 之后的下一个非空格标记,请匹配后跟一个或多个空格,后跟最长的非空格字符序列。--branch--branch

sed 's/\(--branch  *\)[^ ]*/\1main/'

(如果你有这个可以简化为sed -E

sed -E 's/(--branch +)[^ ]*/\1main/'

但这是一个非 POSIX 扩展。

您的尝试只是匹配所有字符,直到行的末尾(即任何字符尽可能多地重复)。.*.*

要匹配下一个非空格、非斜杠标记后,匹配非空格、非斜杠字符的数量尽量多;并且可能使用与斜杠不同的分隔符来简化自己的事情;/blob/[^ /]*

sed 's%\(/blob/\)[^ /]*%\1main%'

如果需要替换字符串来自 shell 变量,则需要使用双引号而不是单引号;然后,这需要您在贝壳会吃掉其中一些的地方使用更多的反斜杠。一个简单的解决方法是在双引号字符串旁边使用单引号字符串,这样你就不需要添加大量的反斜杠;

sed 's%\(/blob/\)[^ /]*%\1'"$branch%"

Stack Overflow 正则表达式标记信息页面包含常见初学者问题的答案和学习材料的链接。

评论

0赞 Ali J. Ghandour 10/22/2023
我现在将使用此解决方案..同时期待使用 GHA 默认环境变量的@Azeem建议