1

我有一个下面提到的要求。

示例文件.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.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>

我正在尝试使用此脚本在两个字符串(包括字符串)之间查找一些文本(。密码。),然后将其替换为占位符。每当我的 cmdlinepasswd 占位符有特殊字符说“/”字符时,它就会失败。

sed -ie "/$datasource/,/password*/ {s/.*password.*/\tpassword=\"$cmdlinepasswd\"/;}"    file.txt

假设 datasource=jdbc/myDBPool1 cmdlinepasswd=new/passwd

我是脚本新手,任何帮助将不胜感激。谢谢你。

4

2 回答 2

1

这应该这样做:

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

它只查找以后跟<Resource开头的记录,name="<your datasource variable value>"如果找到,它将替换该记录中的密码。

如果您已经有 shell 变量

datasource="jdbc/myDBPool1"
cmdlinepasswd="new/passwd"

只需将它们传递给 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
于 2013-08-24T20:53:34.847 回答
0

一种使用的方法。它接受三个参数,检查/替换的变量和输入文件。它比更好,因为它对参数执行 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 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="new/passwd"
       validationQuery="SELECT 1 FROM DUAL"
 />

...

注意:看到您的编辑后,使用xml解析器会是一个更好的选择,但这个解决方案似乎在我的测试中有效。

于 2013-08-24T20:44:27.133 回答