sed-仅执行第一个(第 n 个)匹配的替换?

sed-仅执行第一个(第 n 个)匹配的替换?

假设我有以下文件:

echo "1
2
3
4
1
2
3
4
1
2
3
4
1
2
3
4
" > ztest

这里我只想将第一个改为15其他的都保留原样。

我知道sed有一个quit命令-所以我尝试以下操作:

$ sed 's/1/{5;q}/' ztest 
{5;q}
2
3
4
{5;q}
2
3
4
{5;q}
2
3
4
{5;q}
2
3
4

这会改变所有行,所以这不好。因此,我尝试这样做:

$ sed '{s/1/5/;q}' ztest 
5

现在,这显然按照要求做了 - 更改第一行并退出;但是,我希望其余行保持完整!(因为这样,基本上就相当于用一个“5”替换了整个文件

所以我不知道需要什么样的语法?请注意,我需要这个来内联更改千兆字节文件中的“早期”行(使用sed -i);因此我只想sed在第一个简短部分中进行搜索和替换 - 之后,输出行不变(因为sed -i无论如何都会先转储到临时文件中,然后覆盖原始文件);希望能节省一些处理时间。

提前感谢任何答案,
干杯!

编辑:忘记了子问题:是否可以将其扩展到前 n 个匹配项?(比如,在上面的文件中,前两个“1”更改为 5 - 其余部分是逐字输出?)

答案1

我在这个网站的其他地方看到过:

sed '/1/{s/1/5/;:a;n;ba}' ztest

因此,一旦您找到第一个出现的情况,您就会循环直到文件读取和打印行的末尾。

更新

可以增强它以仅替换第 N 个匹配项。这个想法是将X每个匹配项存储在保留空间中,当所有匹配项X都存在时,循环直到文件末尾。以下是替换第 2 个匹配项的脚本:

sed '/1/{G;s/\nX\{1\}//;tend;x;s/^/X/;x;P;d};p;d;:end;s/1/5/;:a;n;ba'

请注意,您需要在\{和之间放置 (N-1) \}

更新 2

我意识到如果将 替换为 ,P;d则上述内容毫无用处。因此,一个更简单的解决方案是:p;dP;d

sed '/1/{G;s/\nX\{1\}//;tend;x;s/^/X/;x};P;d;:end;s/1/5/;:a;n;ba'

答案2

不知道这是否可行sed,但这里有一个awk版本。

awk 'BEGIN {matches=0}
     matches < 2 && /1/ { sub(/1/,"5"); matches++ }
     { print $0 }' ztest 

这将1用替换5的前两个匹配项1。(更改2其中的 以增加/减少所需的匹配项数量。)
之后,文件将按原样打印。

答案3

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

sed '0,/1/s//5/' file

答案4

:a;n;ba再次使用该模式:

$ sed '/1/{s//5/;:A;/1/{s//5/;:B;n;bB};n;bA}'

相关内容