![如何仅使用 sed 在文本第 N 次出现之前添加文本?](https://linux22.com/image/201056/%E5%A6%82%E4%BD%95%E4%BB%85%E4%BD%BF%E7%94%A8%20sed%20%E5%9C%A8%E6%96%87%E6%9C%AC%E7%AC%AC%20N%20%E6%AC%A1%E5%87%BA%E7%8E%B0%E4%B9%8B%E5%89%8D%E6%B7%BB%E5%8A%A0%E6%96%87%E6%9C%AC%EF%BC%9F.png)
我搜索了之前的问题,但它们只是在出现后添加。我需要它之前:
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
是这项工作的错误工具。使用awk
或perl
代替。例如
$ perl -pe 's/world/++$i == 4 ? "hello world" : $&/ge' input.txt
world world
world hello world
world world
请注意,这使用了/e
perl 正则表达式修饰符,这使得替换运算符的替换部分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'