如何仅使用 sed 在文本第 N 次出现之前添加文本?

如何仅使用 sed 在文本第 N 次出现之前添加文本?

我搜索了之前的问题,但它们只是在出现后添加。我需要它之前:

 world world
 world world
 world world

因此 sed 必须在特定文本第 N 次出现的开头添加“hello”。在这种情况下,我将其添加到第四世界:

world world
world hello world
world world

答案1

如果你绝对必须使用 sed,你可以尝试以下方法,但是正如注释已经明确指出的那样,sed 路线将不稳定。

sed -e '
  H;1h;g
  s/world/HELLO &/4;tn
  $!d;:n;n;bn
' yourfile

答案2

sed是这项工作的错误工具。使用awkperl代替。例如

$ perl -pe 's/world/++$i == 4 ? "hello world" : $&/ge' input.txt 
world world
world hello world
world world

请注意,这使用了/eperl 正则表达式修饰符,这使得替换运算符的替换部分s///被执行为 perl 代码而不是被解释为字符串。

该代码在每次匹配时++$i == 4 ? "hello world" : $&预先递增一个计数器变量 ( $i),如果它等于 4,则将匹配替换为“hello world”,否则将匹配替换为自身 ( $&)。

答案3

我知道你说“使用 sed”,但如果你在现实世界中必须做这样的事情,这里是如何在每个 Unix 机器上的任何 shell 中使用任何 awk 并进行全字字符串比较(请参阅如何找到与模式匹配的文本为什么这很重要):

$ awk -v n=4 '{
    for (i=1;i<=NF;i++) {
        if ( ($i == "world") && (++cnt == n) ) {
            $i = "hello " $i
        }
    }
    print
}' file
world world
world hello world
world world

想象一下您的输入是:

$ cat file
google.com mygoole.comedy
googleycom google.com
google.com google.com

并且您想将“hello”放在第四个之前google.com(现在是输入中的最后一个)。使用上面的 awk 脚本,您只需更改$i=="world"$i=="google.com"

$ cat file
awk -v n=4 '{
    for (i=1;i<=NF;i++) {
        if ( ($i == "google.com") && (++cnt == n) ) {
            $i = "hello " $i
        }
    }
    print
}' file
google.com mygoole.comedy
googleycom google.com
google.com hello google.com

现在尝试使用 sed 脚本执行相同的操作(特别是如果您仅使用 POSIX 语法且没有 GNU 扩展)。现在尝试使用sed 脚本in&out作为替换文本,您会发现更多问题。hello

答案4

sed 'H;1h;$!d;x;s/world/hello &/4' 

相关内容