sed:用换行符在特定模式之后插入行

我们想修改一个plist文件,在匹配一个模式之后,它应该使用sed shell命令插入几行。

plist文件格式如下:

<plist> <dict> . . <key>abc</key> <dict> . . </dict> . . </dict> </plist> 

我们想要在find第一个字典标记后插入几行。

如果我使用follow命令,它插入文件中的所有字典标记。

 sed -i '' "/<dict>/ r template" info.plist 

所以,我试图findplist和dict标签,然后插入行。

 sed -i '' "/<plist version=\"1.0\">\n<dict>/r template" info.plist 

要么

 sed -i '' "/\(^<plist version=*.\)/ r template" info.plist 

这也不起作用,它无法find文件中的模式。

请build议我怎样才能把一个模式,其中包含由换行符分隔的两个string。

sed是一个简单的replace在一个单一的线上的优秀工具,其他的只是使用awk。 如果你在sed中使用s,g和p(带-n)以外的东西,那么你正在使用错误的工具和语言结构,在20世纪70年代中期awk被发明时,这些工具和语言结构已经过时了。

有很多方法可以做到这一点。 这里有一个:

 $ cat file1 <plist> <dict> . . <key>abc</key> <dict> . . </dict> . . </dict> </plist> 

 $ cat file2 now is the winter of our discontent 

 $ awk 'NR==FNR{extra = extra $0 RS; next} {print} /<dict>/ && ++count==1{printf "%s", extra}' file2 file1 <plist> <dict> now is the winter of our discontent . . <key>abc</key> <dict> . . </dict> . . </dict> </plist> 

想在dict的第二次出现之后打印而不是第一次? 只要将==1更改为==2

 $ awk 'NR==FNR{extra = extra $0 RS; next} {print} /<dict>/ && ++count==2{printf "%s", extra}' file2 file1 <plist> <dict> . . <key>abc</key> <dict> now is the winter of our discontent . . </dict> . . </dict> </plist> 

想要search一个跨越多行而不是第N个模式的模式? GNU awk用于多字符RS和gensub()的方法如下:

 $ awk -v RS='^$' 'NR==FNR{extra=$0;next} {print gensub(/<plist>[[:space:]]+<dict>\n/,"&"extra,"")}' file2 file1 <plist> <dict> now is the winter of our discontent . . <key>abc</key> <dict> . . </dict> . . </dict> </plist> 

所有awk的小东西。

用任何UNIX命令更新原始文件是:

 command file > tmp && mv tmp file 

所以在这种情况下是这样的:

 awk 'script' file > tmp && mv tmp file 

GNU awk有一个-i inplace inplace参数,像seds -i一样在后台创buildtmp文件,如果你喜欢边际简洁的话:

 awk -i inplace 'script' file 

这可能适用于你(GNU sed):

 sed -i -e '1,/<dict>/{/<dict>/{r template' -e '}}' file 

尝试使用'N'命令来启用换行匹配:

 sed 'N;/<plist>\n\s\+<dict>/a added line' info.plist