Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

bash - Delete nodes in xml if they contain certain text using sed

I have an xml that looks like following.

<rootNode>  
   <appender name="SERVER_FILE" class="org.apache.log4j.RollingFileAppender">
      <param name="File" value="C:/COM_FIND.log"/>
      <param name="Threshold" value="INFO"/>
      <param name="Append" value="true"/>
      <param name="MaxFileSize" value="5000KB"/>
      <param name="MaxBackupIndex" value="5"/>
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
      </layout>
   </appender>   
   <appender name="CAT_FILE" class="org.apache.log4j.RollingFileAppender">
      <param name="File" value="C:/COM_Now.log"/>
      <param name="Threshold" value="INFO"/>
      <param name="Append" value="true"/>
      <param name="MaxFileSize" value="5000KB"/>
      <param name="MaxBackupIndex" value="2"/>
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
      </layout>
   </appender> 
    <appender name="SERVER_FILE" class="org.apache.log4j.RollingFileAppender">
         <param name="File" value="C:/COM_A.log"/>
         <param name="Threshold" value="INFO"/>
         <param name="Append" value="true"/>
         <param name="MaxFileSize" value="5000KB"/>
         <param name="MaxBackupIndex" value="5"/>
         <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
         </layout>
   </appender>   
    <appender name="SERVER_FILE" class="org.apache.log4j.RollingFileAppender">
         <param name="File" value="C:/COM_Find.log"/>
         <param name="Threshold" value="INFO"/>
         <param name="Append" value="true"/>
         <param name="MaxFileSize" value="5000KB"/>
         <param name="MaxBackupIndex" value="5"/>
         <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
         </layout>
   </appender>   
   <logger name="com.mycompany">
      <level value="INFO"/>
      <appender-ref ref="SERVER_FILE"/>
    </logger>
</rootNode>

Yes.Its an excerpt from the log4j xml. What i basically want to do is remove all the appender tags/elements (from )that contain the word 'COM_Find.log' using the sed command. What i have so far is this :-

sed -e '/<appender/,/</appender>/{H;$!d;}' -e 'x;/COM_Find.log/d' file.xml

Which does a greedy search from the first appender to the last and deletes everything in between. I just want only those specific appender tags/elements(from ) to be removed.

The output should be:-

<rootNode>  
   <appender name="CAT_FILE" class="org.apache.log4j.RollingFileAppender">
      <param name="File" value="C:/COM_Now.log"/>
      <param name="Threshold" value="INFO"/>
      <param name="Append" value="true"/>
      <param name="MaxFileSize" value="5000KB"/>
      <param name="MaxBackupIndex" value="2"/>
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
      </layout>
   </appender> 
    <appender name="SERVER_FILE" class="org.apache.log4j.RollingFileAppender">
         <param name="File" value="C:/COM_A.log"/>
         <param name="Threshold" value="INFO"/>
         <param name="Append" value="true"/>
         <param name="MaxFileSize" value="5000KB"/>
         <param name="MaxBackupIndex" value="5"/>
         <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
         </layout>
   </appender>   
   <logger name="com.mycompany">
      <level value="INFO"/>
      <appender-ref ref="SERVER_FILE"/>
    </logger>
</rootNode>

Can someone help me?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
sed -ne '/rootNode/{ p; b }; /<appender /{ h; b }; /<logger /{ h; b }; H; /</logger>/{ x; p; b; }; /</appender>/{ x; /COM_Find[.]log/b; /COM_FIND[.]log/b; p }' file

Output:

<rootNode>  
   <appender name="CAT_FILE" class="org.apache.log4j.RollingFileAppender">
      <param name="File" value="C:/COM_Now.log"/>
      <param name="Threshold" value="INFO"/>
      <param name="Append" value="true"/>
      <param name="MaxFileSize" value="5000KB"/>
      <param name="MaxBackupIndex" value="2"/>
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
      </layout>
   </appender> 
    <appender name="SERVER_FILE" class="org.apache.log4j.RollingFileAppender">
         <param name="File" value="C:/COM_A.log"/>
         <param name="Threshold" value="INFO"/>
         <param name="Append" value="true"/>
         <param name="MaxFileSize" value="5000KB"/>
         <param name="MaxBackupIndex" value="5"/>
         <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
         </layout>
   </appender>   
   <logger name="com.mycompany">
      <level value="INFO"/>
      <appender-ref ref="SERVER_FILE"/>
    </logger>
</rootNode>

Another for awk:

awk '{ p = 1 } /<appender /{ t = $0; while (getline > 0) { t = t ORS $0; if (/COM_FIND[.]log/ || /COM_Find[.]log/) p = 0; if (/</appender>/) break } $0 = t } p' file

Or GNU awk with IGNORECASE:

gawk -v IGNORECASE=1 '{ p = 1 } /<appender /{ t = $0; while (getline > 0) { t = t ORS $0; if (/COM_FIND[.]log/) p = 0; if (/</appender>/) break } $0 = t } p' file

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...