Shell,查找包含的行,并在其后仅替换行

时间:2015-02-03 04:57:59

标签: bash shell

我的文件位于:/Applications/Firefox.app/Contents/info.plist。我想找到包含LSUIElement的行,然后用<string>firefox</string>替换整行。

这就是我所得到的,到目前为止,它什么也没做:

line=“LSUIElement”
rep="<string>firefox</string>"
sed -e "s/${line}/${rep}/g" /Applications/Firefox.app/Contents/info.plist > /Applications/Firefox.app/Contents/info.plist.profilist
mv /Applications/Firefox.app/Contents/info.plist.profilist /Applications/Firefox.app/Contents/info.plist 

2 个答案:

答案 0 :(得分:1)

使用 awk ,您可以执行以下操作:

awk '/LSUIElement/{i=NR+1}{if(NR==i){gsub(/1/,"0",$0)}}1' File > tmp && mv tmp File

<强>逻辑: 如果找到LSUIElement,请将变量i设置为NR+1(即下一行/记录号)。作为第二部分,如果NR(当前记录/行)为i(之前已保存),请将1替换为0。因此,替换将仅发生在具有模式LSUIElement的行之后的行中。

答案 1 :(得分:0)

让那些手头没有这样一个plist文件的人简化问题。

echo -e "foo bar baz\nthe suspicious LSUIElement in line 2\nand some more garbage" > luis.txt 
cat luis.txt
foo bar baz
the suspicious LSUIElement in line 2
and some more garbage

line=“LSUIElement”
rep="<string>firefox</string>"

所以这里我们有问题1:sed表达式中的斜杠通常将部分分开,例如&#39; s / a / b / g&#39;。

sed -e "s/${line}/${rep}/g" luis.txt > luis2.txt 
mv luis2.txt luis.txt 

我们首先选择低挂水果。 Sed,至少是Gnu-sed,有一个选项-i来改变文件。在后台,可能会有一个 复制正在进行,因为文件经常缩小或增长,所以很难避免,但我们不需要重定向和mv:

sed -i "s/${line}/${rep}/g" luis.txt

您甚至可以让sed生成备份文件。在正常情况下,AFAIK sed并不需要-e,但可能是,gnu-sed在这种情况下是特殊的。测试或阅读手册页。

现在是困难的部分。我们测试没有-i以避免破坏。第一次测试,第一次惊喜:

line=“LSUIElement”
rep="<string>firefox</string>"
echo $line
# “LSUIElement”
echo $rep
# <string>firefox</string>

为什么显示引号,但 rep 不显示?啊,这些都是印刷报价?这有什么重要意义吗?那你应该提一下,因为它很容易监督。在决定要求之前,我决定不去。

如果我们用|替换sed表达式中的/,我们可以避免在$ rep变量中与sed-syntax冲突:

sed "s|${line}|${rep}|g" luis.txt
foo bar baz
the suspicious <string>firefox</string> in line 2
and some more garbage

这里我们完全取代了模式,而不是线条。

sed "s|.*${line}.*|${rep}|g" luis.txt
foo bar baz
<string>firefox</string>
and some more garbage

这取代了整条生产线。

sed "s|${line}.*|${rep}|g" luis.txt
foo bar baz
the suspicious <string>firefox</string>
and some more garbage

这正在从模式中取代,直到EOL。

如果我们想在下一行中更换一些东西 - 那么取而代之的是什么?例如,垃圾

我们可以匹配$ line而不替换它,但是调用一系列短命令的2个命令,&#39; n&#39;为了阅读下一行&#39;并在那里执行我们的替换。这些命令必须包含在{}中。因为我们不需要改变/到|在前一部分,我们切换回那里:

sed "/${line}.*/{n;s|garbage|$rep|}" luis.txt
foo bar baz
the suspicious LSUIElement in line 2
and some more <string>firefox</string>

命令:

sed -i.bak "/${line}.*/{n;s|garbage|$rep|}" luis.txt

会创建一个这样的备份文件luis.txt.bak

使用模式,正如评论中注意到的那样,这看起来像:

sed -i.bak "/${line}.*/{n;s|<string>.*</string>|$rep|}" luis.txt

决定它必须具体(1,数字,无关紧要)。