假设我有以下文件:
echo "1
2
3
4
1
2
3
4
1
2
3
4
1
2
3
4
" > ztest
这里我只想将第一个改为1
,5
其他的都保留原样。
我知道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;d
P;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}'