Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在不更改相同字符串的情况下修改XML文件中的字符串_Bash_Sed - Fatal编程技术网

Bash 在不更改相同字符串的情况下修改XML文件中的字符串

Bash 在不更改相同字符串的情况下修改XML文件中的字符串,bash,sed,Bash,Sed,我正在编写一个bash脚本,需要它来更改XML文件,用“disabledController”替换一堆不同的servlet名称项 我知道我可以使用sed来实现这一点,但是有两个不同的行具有相同的字符串,但只需要更改一个 例如,我需要更改以下内容: <servlet> <servlet-name>CreateCertificateAuthorityBackup</servlet-name> <servlet-class>

我正在编写一个bash脚本,需要它来更改XML文件,用“disabledController”替换一堆不同的servlet名称项

我知道我可以使用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>

CreateCertificateAuthorityBackup
com.company.ca.CABackup
CreateCertificateAuthorityBackup
createCertificateAuthorityBackup
为此:

<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>

CreateCertificateAuthorityBackup
com.company.ca.CABackup
禁用控制器
createCertificateAuthorityBackup
如果我这样使用sed:

sed "s@<servlet-name>CreateCertificateAuthorityBackup.*@<servlet-name>disabledController</servlet-name>@"
sed”s@CreateCertificateAuthorityBackup.*@禁用的控制器@”

它将替换两个servlet名称项,而不仅仅是第二个。有什么方法可以完成我想在这里执行的操作吗?

要仅替换第二个引用,请使用从文件开头开始的嵌套和图案范围:

sed -i '0,/CreateCertificateAuthorityBackup/! { 0,//s//disabledController/ }' file
或全部:

sed -i '0,/CreateCertificateAuthorityBackup/! { 0,/CreateCertificateAuthorityBackup/s/CreateCertificateAuthorityBackup/disabledController/ }' file
对长柄命令的解释:

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映射”标记之间进行更改,您只需要一个模式范围:

sed '/<servlet-mapping>/,/<\/servlet-mapping>/s/CreateCertificateAuthorityBackup/disabledController/' file
sed'//,//s/CreateCertificateAuthorityBackup/disabledController/'文件

您可能想了解更多有关图案范围的信息。HTH.

要仅替换第二个引用,请使用从文件开头开始的嵌套和图案范围:

sed -i '0,/CreateCertificateAuthorityBackup/! { 0,//s//disabledController/ }' file
或全部:

sed -i '0,/CreateCertificateAuthorityBackup/! { 0,/CreateCertificateAuthorityBackup/s/CreateCertificateAuthorityBackup/disabledController/ }' file
对长柄命令的解释:

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映射”标记之间进行更改,您只需要一个模式范围:

sed '/<servlet-mapping>/,/<\/servlet-mapping>/s/CreateCertificateAuthorityBackup/disabledController/' file
sed'//,//s/CreateCertificateAuthorityBackup/disabledController/'文件

您可能想了解更多有关图案范围的信息。HTH.

使用XML工具修改XML。这使得解决方案比将其作为文本处理更健壮,更符合标准。如果文件按照XML规则重新格式化,则替换不会失败,如果其他XML标准工具对同一文件进行操作,则替换不会中断

您可以使用
xmlstarlet
替换
servlet映射
,其
servlet名称
值为
CreateCertificateAuthorityBackup
,如下所示:

xmlstarlet edit -L \
  -u '/web-app/servlet-mapping/servlet-name[normalize-space(text())="CreateCertificateAuthorityBackup"]' \
  -v "disabledController"  web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <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>
</web-app>
给定如下
web.xml

xmlstarlet edit -L \
  -u '/web-app/servlet-mapping/servlet-name[normalize-space(text())="CreateCertificateAuthorityBackup"]' \
  -v "disabledController"  web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <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>
</web-app>

CreateCertificateAuthorityBackup
com.company.ca.CABackup
CreateCertificateAuthorityBackup
createCertificateAuthorityBackup

使用XML工具修改XML。这使得解决方案比将其作为文本处理更健壮,更符合标准。如果文件按照XML规则重新格式化,则替换不会失败,如果其他XML标准工具对同一文件进行操作,则替换不会中断

您可以使用
xmlstarlet
替换
servlet映射
,其
servlet名称
值为
CreateCertificateAuthorityBackup
,如下所示:

xmlstarlet edit -L \
  -u '/web-app/servlet-mapping/servlet-name[normalize-space(text())="CreateCertificateAuthorityBackup"]' \
  -v "disabledController"  web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <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>
</web-app>
给定如下
web.xml

xmlstarlet edit -L \
  -u '/web-app/servlet-mapping/servlet-name[normalize-space(text())="CreateCertificateAuthorityBackup"]' \
  -v "disabledController"  web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <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>
</web-app>

CreateCertificateAuthorityBackup
com.company.ca.CABackup
CreateCertificateAuthorityBackup
createCertificateAuthorityBackup

我认为xmlstarlet有这样做的选择,我认为xmlstarlet有这样做的选择,您能详细介绍一下这里实际发生的事情吗?而且,有时需要改变的不是第二个。在极少数情况下,它可能是第一个或第三个。@jkitzmiller:你说过你想替换“仅仅是第二个”事件。您如何定义要更改的事件?你说你想替换上一个事件是正确的吗?很公平,我确实这么说了。我认为最准确的表述方式是,我想更改servlet映射标记中出现的内容。@jkizmiller:请参阅我上面的编辑。它将仅在打开和关闭“servlet映射”标记之间执行替换。史蒂夫,这正是我需要的。非常感谢。你能详细说明一下这里到底发生了什么吗?而且,有时需要改变的不是第二个。在极少数情况下,它可能是第一个或第三个。@jkitzmiller:你说过你想替换“仅仅是第二个”事件。您如何定义要更改的事件?你说你想替换上一个事件是正确的吗?很公平,我确实这么说了。我认为最准确的表述方式是,我想更改servlet映射标记中出现的内容。@jkizmiller:请参阅我上面的编辑。它将仅在打开和关闭“servlet映射”标记之间执行替换。史蒂夫,这正是我需要的。非常感谢。