1

I am creating a bash script to setup tomcat server. I need to comment some contents from context.xml file. I tried with sed but not able match the contents.

Here is full context.xml file:


 <?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<Context antiResourceLocking="false" privileged="true" >
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

I need to comment out the following line:

<Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />

Here is what I tried to replace the <Value......./> with <!-- <Value........./> -->

sed '/^a test$/{$!{N;s/^<Valve className="org.apache.catalina.valves.RemoteAddrValve"\n\s.*allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" \/>/<!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve"\n         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" \/>-->/;ty;P;D;:y}}' context.xml

The command runs without any error but it is not changing anything in original file. I guess the problem is because of new lines & extra space. I found solution for new line in How can I use sed to replace a multi-line string? and added \s* to skip the space but it is still not working. I am not able to find any alternative for this.

Is there any easy way to achieve this? Or what is wrong with my command?

1
  • 2
    Oh dear!, that's a long command. You can't really expect it to do anything if the first thing you try to match is /^a test$/, which is not in your input file. Please review that part and edit your question.
    – Quasímodo
    May 27, 2020 at 23:07

3 Answers 3

3

Try:

sed '{$!{N;s/<Valve.*\n.*allow.* \/>/<!-- & -->/;ty;P;D;:y}}' content.xml

It outputs:

...
<Context antiResourceLocking="false" privileged="true" >
  <!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

Can easily be modified to put the comment tags on separate lines if so desired, i.e.

sed '{$!{N;s/<Valve.*\n.*allow.* \/>/<!--\n&\n-->/;ty;P;D;:y}}' content.xml
1
  • While I provided a sed-based solution, I do believe the best solution would be an appropriate XSLT transformation.
    – fpmurphy
    May 28, 2020 at 11:32
2

Try this:

sed -r '/^\s*<Valve className\s*=\s*"org\.apache\.catalina\.valves\.RemoteAddrValve"\s*$/{h;z;N;s:^\n::;H;/^\s*allow\s*=\s*"127\\\.\\d\+\\\.\\d\+\\\.\\d\+\|::1\|0:0:0:0:0:0:0:1"\s*\/>\s*$/{g;s/.*/<!--\n&\n-->/}}' context.xml

Output:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<Context antiResourceLocking="false" privileged="true" >
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
-->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>
2

Using xsltproc or xmlstarlet with an XSL transformation in transform.xsl:

<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:template match="/|node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/Context/Valve">
    <xsl:text disable-output-escaping="yes">&lt;!-- </xsl:text>
    <xsl:copy-of select="."/>
    <xsl:text disable-output-escaping="yes"> --&gt;</xsl:text>
  </xsl:template>

</xsl:transform>

The first template is just an identity transformation, while the second template inserts <!-- and --> around the /Context/Valve node.

If you need to match the exact values of the attributes in the node, then do so with a more specific XPath query in the match of the second template:

<xsl:template match="/Context/Valve[
      @className='org.apache.catalina.valves.RemoteAddrValve' and
      @allow='127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1'
]">

Applying it can be done with xmlstarlet tr transform.xsl file.xml or with xsltproc transform.xsl file.xml:

$ xsltproc transform.xsl file.xml
<?xml version="1.0"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<Context antiResourceLocking="false" privileged="true">
  <!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1"/> -->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

This would handle commenting out the node whatever the formatting of it happens to be.

If it's a static file that won't change, then just insert the comment markup on the correct lines:

sed '17s/^/<!-- /; 18s/$/ -->/' file.xml
2
  • 1
    You can also use xsltproc which is installed by default on many distributions. xsltproc transform.xsl file.xml
    – fpmurphy
    May 28, 2020 at 12:12
  • @fpmurphy Thanks, I've included that.
    – Kusalananda
    May 28, 2020 at 12:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .