我正在编写一个bash脚本,我需要它来更改XML文件,用“disabledController”替换一堆不同的servlet-name项。
我知道我可以使用sed执行此操作,但是有两个不同的行具有相同的字符串,但只需要更改一个。
例如,我需要改变这个:
<servlet>
<servlet-name>CreateCertificateAuthorityBackup</servlet-name>
<servlet-class>com.company.ca.CABackup</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CreateCertificateAuthorityBackup</servlet-name>
<url-pattern>createCertificateAuthorityBackup</url-pattern>
</servlet-mapping>
进入这个:
<servlet>
<servlet-name>CreateCertificateAuthorityBackup</servlet-name>
<servlet-class>com.company.ca.CABackup</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>disabledControler</servlet-name>
<url-pattern>createCertificateAuthorityBackup</url-pattern>
</servlet-mapping>
如果我像这样使用sed:
sed "s@<servlet-name>CreateCertificateAuthorityBackup.*@<servlet-name>disabledController</servlet-name>@"
它取代了两个servlet-name项而不是第二个。有办法做我想做的事吗?
答案 0 :(得分:1)
要仅替换第二次出现,请使用从文件开头开始的嵌套和模式范围:
sed -i '0,/CreateCertificateAuthorityBackup/! { 0,//s//disabledController/ }' file
或完整:
sed -i '0,/CreateCertificateAuthorityBackup/! { 0,/CreateCertificateAuthorityBackup/s/CreateCertificateAuthorityBackup/disabledController/ }' file
longhand命令的说明:
0,/CreateCertificateAuthorityBackup/ # is a pattern range from the start of
# the file to the first occurrence of:
# 'CreateCertificateAuthorityBackup'
! { ... } # if not in the above pattern range, do
# every between the braces.
0,/CreateCertificateAuthorityBackup/ # match between the beginning of the
# file again and the next occurrence
# of 'CreateCertificateAuthorityBackup'
s/ ... / ... / # perform the necessary substitution
如果您想要替换第三个匹配项,只需添加另一个嵌套层:
sed '0,/CreateCertificateAuthorityBackup/! { 0,//! { 0,// s//disabledController/ } }' file
编辑:
要在'servlet-mapping'标签之间进行更改,您只需要一个模式范围:
sed '/<servlet-mapping>/,/<\/servlet-mapping>/s/CreateCertificateAuthorityBackup/disabledController/' file
您可能希望详细了解模式范围here。 HTH。
答案 1 :(得分:0)
使用XML工具修改XML。这使得该解决方案比将其视为文本更加健壮且符合标准。如果根据XML规则重新格式化文件,则替换不会失败,并且如果其他XML标准工具在同一文件上运行,则不会中断。
您可以使用xmlstarlet
替换servlet-mapping
值为servlet-name
的{{1}},如下所示:
CreateCertificateAuthorityBackup
给出这样的xmlstarlet edit -L \
-u '/web-app/servlet-mapping/servlet-name[normalize-space(text())="CreateCertificateAuthorityBackup"]' \
-v "disabledController" web.xml
:
web.xml