我正在尝试替换上一行搜索中的内容。
我的档案:
<RECORD>
<TOKEN data = "670"/>
<ID data ="10647043"/>
<NAME data="m11111"/>
如果我搜索m11111,那么我需要转到上一行并用不同的值替换10647043。我试过的Sed:
sed '/m11111/{g;/=/s/=.*/="9283"\/>/g;};h' test.txt
sed有办法吗?如果不与sed,任何其他方式做到这一点?
由于 阿贾伊
答案 0 :(得分:4)
假设test.txt
的大小不是千兆字节且你有GNU sed(在Mac上使用),请尝试:
$ sed -zE 's/10647043([^\n]*\n[^\n]*m11111)/9283\1/' test.txt
<RECORD>
<TOKEN data = "670"/>
<ID data ="9283"/>
<NAME data="m11111"/>
-z
这告诉sed一次读取整个文件。从技术上讲,它读取直到NUL字符,但由于没有合理的文本文件有NUL字符,这实际上与读取整个文件相同。
-E
这告诉sed使用扩展正则表达式,这样我们就不必输入那么多反斜杠。
s/10647043([^\n]*\n[^\n]*m11111)/9283\1/
这样查找10647043跟随除换行符之外的任何字符,后跟换行符,跟随除换行符之外的任何字符,后跟m11111。这将10647043替换为9283,保持其他所有内容相同。
sed -E 'H;1h;$!d;x; s/10647043([^\n]*\n[^\n]*m11111)/9283\1/' test.txt
此处的更改是使用H;1h;$!d;x
一次读取整个文件。
一次只读一行。如果当前行包含m11111,则修改前一行(存储在变量last
中)。
$ awk '/m11111/{sub(/10647043/, "9283", last)} NR>1{print last} {last=$0} END {print last}' test.txt
<RECORD>
<TOKEN data = "670"/>
<ID data ="9283"/>
<NAME data="m11111"/>
答案 1 :(得分:0)
这可能是一个比@ John1024更慢的解决方案,但它是一个sed
唯一的解决方案,它不会将整个文件读入内存(它需要两次通过)。
sed -i '$!N;/\n.*m11111/s/"\([^"]*\)"/"9243"/' filename
sed -i '1n; $!N;/\n.*m11111/s/"\([^"]*\)"/"9243"/' filename
正如@ John1024指出的那样,如果sed
出现在偶数行上,则第一个m11111
会替换现有引号中的先前内容;第二行重复该过程,但忽略第一行以覆盖所有奇数行。