【问题标题】:Using sed - how to replace the first occurrence of a string on the line after the first occurrence of a variable使用sed - 如何在第一次出现变量后替换第一次出现的字符串
【发布时间】:2021-12-05 07:17:33
【问题描述】:

我在使用 sed 将变量用作搜索字符串时遇到了一点分层问题AND 跨多行执行此操作。我可以做任何一个,但不能同时做。我正在处理一个看起来像这样的 xml 文件。

<tag property="search1">
        string
</tag>
<tag property="search2">
        string
</tag>
<tag property="search3">
        string
</tag>

我正在尝试使用脚本将“string”顺序替换为另一个值,具体取决于它之前行上“search”字符串的数量。脚本会增加一个计数器来执行此操作。

如果“$n”已知,我可以在“search$n”之后找到并替换“string”:

$ sed '$!N;/search2/ s/\string/foo/;P;D' test
<tag property="search1">
        string
</tag>
<tag property="search2">
        foo
</tag>
<tag property="search3">
        string
</tag>

我可以根据变量搜索替换字符串:

$ n=2 
$ sed "/search$n/ s/search/foo/" test
<tag property="search1">
        string
</tag>
<tag property="foo2">
        string
</tag>
<tag property="search3">
        string
</tag>

但我一直无法弄清楚如何将两者结合起来:

$ sed '$!N;/search$n/ s/\string/foo/;P;D' test

上述命令有效;因为它不会引发错误,但不会解析变量 - 我尝试过对其进行转义,并将其放在双引号或单引号中并转义。允许我在 sed 中解析多行的参数似乎需要单引号,而在搜索字段中读取变量需要双引号...

我在 OSX 上并使用 gnu-sed。以下是我尝试过的其他一些事情:

sed "/search$n/,+1s/string/foo/" test
sed '/search$n/,+1s/string/foo/' test
sed "/search$n/,+1s s/string/foo/" test
sed '/search$n/,+1 s/string/foo/' test
sed '' -e '/search$n/ {' -e 'n; s/string/foo/' -e '}' test 
sed '' -e '/search$n/ {' -e 'n; s/.*/foo/' -e '}' test 
sed '/search$n/!b;n;c/foo/' test 
sed '' -e '/search$n/!b;n;string' test 
sed '' -e "/search$n/ {' -e 'n; s/string/foo/' -e '}" test 
sed '' -e "/search$n/ {' -e 'n; s/.*/foo/g' -e '}" test 
sed '' -e "/search$n/ s/string/foo/" test 
sed -e "/search$n/ s/string/foo/" test 
sed "/search$n/ s/string/foo/" test 

【问题讨论】:

    标签: bash macos variables sed


    【解决方案1】:

    您需要声明n=2(而不是i=2),然后使用双引号来允许变量扩展。

    但是,您需要注意 Bash 特有的 $!。 你可以使用

    n=2
    sed '$!'"N;/search$n/ s/string/foo/;P;D" test
    

    输出:

    <tag property="search1">
            string
    </tag>
    <tag property="search2">
            foo
    </tag>
    <tag property="search3">
            string
    </tag>
    

    '$!'"N;/search$n/ s/string/foo/;P;D"$!(不支持变量扩展)和N;/search$n/ s/string/foo/;P;D(支持变量扩展)的串联。

    【讨论】:

    • 我使用的是n=2,这是一个错字。当我使用您建议的命令时,我得到:$ sed "\$!N;/search$n/ s/string/foo/;P;D" test bash: !N: event not found
    • @Dysclidean 那你也需要处理!,使用sed '$!'"N;/search$n/ s/string/foo/;P;D" test
    【解决方案2】:

    这可能对你有用(GNU sed):

    n=2
    sed '/search'"$n"'/{n;s/string/foo/}' file
    

    n 设置为2

    匹配search2,打印当前行并获取下一行。

    如果以下行包含string,则将string 替换为foo

    以下行可能不包含string,但包含search2,在这种情况下:

    sed ':a;/search'"$n"'/{n;s/string/foo/;Ta}' file
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-07
      • 2011-08-25
      • 2016-11-02
      相关资源
      最近更新 更多