Sed 查找XML文件中两个占位符之间的文本,并将其替换为具有特殊字符的占位符
我有一个下面提到的要求 示例文件.txt::Sed 查找XML文件中两个占位符之间的文本,并将其替换为具有特殊字符的占位符,sed,perl,Sed,Perl,我有一个下面提到的要求 示例文件.txt:: <?xml version='1.0' encoding='utf-8'?> <Server port="${shutdown.port}" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.core.JasperListener" /> <Listener className="org.apache.catalina.core.Jr
<?xml version='1.0' encoding='utf-8'?>
<Server port="${shutdown.port}" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="com.springsource.tcserver.serviceability.rmi.JmxSocketListener"
port="${jmx.port}"
bind="127.0.0.1"
useSSL="false"
passwordFile="${catalina.base}/conf/jmxremote.password"
accessFile="${catalina.base}/conf/jmxremote.access"
authenticate="true"/>
<Listener className="com.springsource.tcserver.serviceability.deploy.TcContainerDeployer" />
<GlobalNamingResources>
<Resource
name="jdbc/myDBPool1"
auth="Container"
type="oracle.jdbc.pool.OracleDataSource"
description="Oracle Datasource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:@localhost:<dbanme>"
user="myusername"
password="somepassword1"
validationQuery="SELECT 1 FROM DUAL"
/>
<Resource
name="jdbc/myDBPool2"
auth="Container"
type="oracle.jdbc.pool.OracleDataSource"
description="Oracle Datasource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:@localhost:<dbanme>"
user="myusername"
password="somepassword2"
validationQuery="SELECT 1 FROM DUAL"
/>
<Resource
name="jdbc/myDBPool3"
auth="Container"
type="oracle.jdbc.pool.OracleDataSource"
description="Oracle Datasource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:@localhost:<dbanme>"
user="myusername"
password="somepassword3"
validationQuery="SELECT 1 FROM DUAL"
/>
</GlobalNamingResources>
<Service name="Catalina">
<Executor name="tomcatThreadPool" namePrefix="tomcat-http--" maxThreads="300" minSpareThreads="50"/>
<Connector executor="tomcatThreadPool"
port="${http.port}"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="${https.port}"
acceptCount="100"
maxKeepAliveRequests="15"/>
<Engine name="Catalina" defaultHost="localhost">
<!--
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
-->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true" deployOnStartup="true" deployXML="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
</Server>
假定
datasource=jdbc/myDBPool1
cmdlinepasswd=new/passwd
我是新的脚本和任何帮助将不胜感激。
谢谢。单向使用。它接受三个参数:要检查/替换的变量和输入文件。这比使用quotemeta(\Q
)对参数进行转义要好,因为它可以转义正则表达式的许多特殊字符
perl -pe '
## Get arguments but input file.
BEGIN { ($datasource,$cmdlinepasswd) = (shift,shift) }
## Get a range from resource name until the line with the password.
if ( $range = ( m/=\s*"\Q${datasource}"/ ... /password\s*=/ ) ) {
## "E0" points to last line (that contains the password, so
## change it.
if ( q|E0| eq substr $range, -2 ) {
s/(=\s*").*("\s*)$/$1${cmdlinepasswd}$2/;
}
}
' "$datasource" "$cmdlinepasswd" infile
对于您的示例输入数据,它将产生(仅显示修改的部分密码,其余部分未被更改):
...
注意:在查看您的编辑后,使用xml
解析器将是一个更好的选择,但在我的测试中,此解决方案似乎有效。单向使用。它接受三个参数:要检查/替换的变量和输入文件。这比使用quotemeta(\Q
)对参数进行转义要好,因为它可以转义正则表达式的许多特殊字符
perl -pe '
## Get arguments but input file.
BEGIN { ($datasource,$cmdlinepasswd) = (shift,shift) }
## Get a range from resource name until the line with the password.
if ( $range = ( m/=\s*"\Q${datasource}"/ ... /password\s*=/ ) ) {
## "E0" points to last line (that contains the password, so
## change it.
if ( q|E0| eq substr $range, -2 ) {
s/(=\s*").*("\s*)$/$1${cmdlinepasswd}$2/;
}
}
' "$datasource" "$cmdlinepasswd" infile
对于您的示例输入数据,它将产生(仅显示修改的部分密码,其余部分未被更改):
...
注意:在查看您的编辑后,使用xml
解析器将是一个更好的选择,但此解决方案在我的测试中似乎有效。这应该可以做到:
awk -v RS= -v ORS='\n\n' -v datasource="jdbc/myDBPool1" -v cmdlinepasswd="new/passwd" '
$0 ~ "^[[:space:]]*<Resource.*name=\"" datasource "\"" {
sub(/password="[^"]+"/,"password=\"" cmdlinepasswd "\"")
} 1' file
只需将它们作为以下内容传递到awk中:
awk -v RS= -v ORS='\n\n' -v datasource="$datasource" -v cmdlinepasswd="$cmdlinepasswd" '
$0 ~ "^[[:space:]]*<Resource.*name=\"" datasource "\"" {
sub(/password="[^"]+"/,"password=\"" cmdlinepasswd "\"")
} 1' file
awk-v RS=-v ORS='\n\n'-v datasource=“$datasource”-v cmdlinepasswd=“$cmdlinepasswd”'
$0~“^[:space:][]*这应该可以做到:
awk -v RS= -v ORS='\n\n' -v datasource="jdbc/myDBPool1" -v cmdlinepasswd="new/passwd" '
$0 ~ "^[[:space:]]*<Resource.*name=\"" datasource "\"" {
sub(/password="[^"]+"/,"password=\"" cmdlinepasswd "\"")
} 1' file
只需将它们作为以下内容传递到awk中:
awk -v RS= -v ORS='\n\n' -v datasource="$datasource" -v cmdlinepasswd="$cmdlinepasswd" '
$0 ~ "^[[:space:]]*<Resource.*name=\"" datasource "\"" {
sub(/password="[^"]+"/,"password=\"" cmdlinepasswd "\"")
} 1' file
awk-v RS=-v ORS='\n\n'-v datasource=“$datasource”-v cmdlinepasswd=“$cmdlinepasswd”'
$0~“^[:space:][]*是否要查找名为datasource
variable的资源,并用cmdlinepasswd
variable的内容替换其密码?@Birei:是的,这是必需的。感谢您的回复。sed
这项任务会更困难吗。是否可以选择使用更强大的工具,如perl
或python
?@Birei:perl就可以了。sed是一个很好的工具,可以在一行上进行简单替换,但对于任何其他文本处理,您都应该使用awk。每条记录之间是否有两条虚线?请更新您发布的示例输入,使其与输入完全一致,包括每条记录之间的内容(如果有)。您只是说要更改具有特定名称
值的记录中的密码,例如jdbc/myDBPool1
?是否要查找名为datasource
变量的资源,并用cmdlinepasswd
变量的内容替换其密码?@Birei:是的,这是必需的。感谢您的回复。sed
这项任务会更困难吗。是否可以选择使用更强大的工具,如perl
或python
?@Birei:perl就可以了。sed是一个很好的工具,可以在一行上进行简单替换,但对于任何其他文本处理,您都应该使用awk。每条记录之间是否有两条虚线?请更新您发布的示例输入,使其与输入完全一致,包括每条记录之间的内容(如果有)。您只是说要更改具有特定名称
值(如jdbc/myDBPool1
)的记录中的密码吗?谢谢。。这似乎很有效。您能告诉我如何更换(并保存)它吗。脚本现在在替换后回显输出。只是删除了注释并将此脚本用作。perl-pe'BEGIN{($datasource,$cmdlinepasswd)=(shift,shift)}if($range=(m/=“\Q${datasource}”/…/password=/){if(Q | E0 | eq substr$range,-2){s/(=”。(“\s*)$/$1${cmdlinepasswd 2/;}$$datasource cmdlinepasswd文件。xml@user2714227:与使用sed时相同。开关-i
对两者都有相同的含义。非常感谢您抽出时间,解决方案非常有效。。。非常感谢。。。!!这是我用过的。perl-i-pe'BEGIN{($datasource,$cmdlinepasswd)=(shift,shift)}if($range=(m/=“\Q${datasource}”/…/password=/){if(Q | E0 | eq substr$range,-2){s/(=”。(“\s*)$/$1${cmdlinepasswd 2/}}$$datasource cmdlinepasswd server.xmlYa,如前所述,使用双引号。。在上面的评论中漏掉了。谢谢。。这似乎很有效。您能告诉我如何更换(并保存)它吗。脚本现在在替换后回显输出。只是删除了注释并将此脚本用作。perl-pe'BEGIN{($datasource,$cmdlinepasswd)=(shift,shift)}if($range=(m/=“\Q${datasource}”/…/password=/){if(Q | E0 | eq substr$range,-2){s/(=”。(“\s*)$/$1${cmdlinepasswd 2/;}$$datasource cmdlinepasswd文件。xml@user2714227:与使用sed时相同。开关-i
对两者都有相同的含义。非常感谢您抽出时间,解决方案非常有效。。。非常感谢。。。!!这是我用过的。perl-i-pe'BEGIN{($datasource,$cmdlinepasswd)=(shift,shift)}if($range=(m/=“\Q${datasource}”/…/password=/){if(Q | E0 | eq substr$range,-2){s/(=”。(“\s*)$/$1${cmdlinepasswd 2/}}$$datasource cmdlinepasswd server.xmlYa,如前所述,使用双引号。。在上面的评论中遗漏了它。感谢您提供的解决方案。但是,如果我们把“name”放在某个地方,并且不在@user2714227的正下方,那会怎么样呢?这没有什么区别,脚本将按原样工作。::Ok ED.将检查一下。感谢您的及时帮助。当“name”、“=”和“datasourcename”之间没有空格(如name=“jdbc/myDBPool1”)时,上述awk脚本工作得非常好,没有任何问题,但真正的问题是当您有空格(如name=“jdbc/myDBPool1”)时,脚本无法执行搜索和替换。能溜溜球吗