Bash

如何使用 ksh 中的關鍵字 grep xml 文件中的 xml 塊

  • October 25, 2016

我有一個文件 Sample.xml,其中包含很多服務,結構看起來像這樣

筆記:

  1. 我無法使用任何 XML 解析器工具,因為我沒有權限,只讀
  2. 我的 xmllint 版本不支持 xpath,無法更新,只讀
  3. 我沒有 xmlstarlet,無法安裝

問題:輸入:隊列名稱

輸出:服務塊

範例輸入:ABC.getme2

需要的輸出:

<service name="GETME2" min="1" max="10" idleTime="300" backend="ABC">
                           <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                           <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                           </handlerContainer>
                           <mqListener queue="ABC.getme2" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
                   </service>

XML結構:

    <?xml version="1.0" encoding="UTF-8"?>
       <deploymentconfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
               <configfile>sample.xml</configfile>
               <exceptionsFilterConfigFile>asdasd.xml</exceptionsFilterConfigFile>
               <keyInfoConfigFile>asdasd.xml</keyInfoConfigFile>
               <services>

   <service name="GETME" min="1" max="10" idleTime="300" backend="ABC">
                           <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                           <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                           </handlerContainer>
                           <mqListener queue="ABC.getme" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
                   </service>

   <service name="GETME2" min="1" max="10" idleTime="300" backend="ABC">
                           <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                           <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                           </handlerContainer>
                           <mqListener queue="ABC.getme2" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
                   </service>
       . . . .a lot of services like this . . . .
       . . . .a lot of services like this . . . .
       . . . .a lot of services like this . . . .
       . . . .a lot of services like this . . . .
       </services>
  <batchServices>
                       <batchService name="batch1">
                               <executor className="com.abc.xyz.qwer.qweqwewqe.ffdsdfsdfsdfsdf" />
                       </batchService>
                       <batchService name="batch2">
                               <executor className="com.abc.xyz.qwer.qweqwewqe.zxcsadsad" />
                       </batchService>
. . . .a lot of batch services like this . . . .
       . . . .a lot of batch services like this . . . .
       . . . .a lot of batch services like this . . . .
       . . . .a lot of batch services like this . . . .
     </batchServices>

<timerservices>
<timerservice> - a lot of timeservice
</timerservices>

 <connectionPools>
               <pool>
                       <name>asdasd</name>
                       <driver>oracle.jdbc.driver.OracleDriver</driver>
                       <url>$asdasd_URL</url>
                       <userId>$asdasd_USER</userId>
                       <password>$asdasd_PASSWORD</password>
                       <minConnections>0</minConnections>
                       <maxConnections>10</maxConnections>
                       <poolUrl>jdbc:asdsad:asdasdsad</poolUrl>
                       <testSql>select * from abc</testSql>
               </pool>

. . a lot of pools. . .

</connectionpools>

</deploymentconfig>

我需要像這樣grep一個xml塊:

<service name="GETME" min="1" max="10" idleTime="300" backend="ABC">
                       <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                       <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                       </handlerContainer>
                       <mqListener queue="ABC.getme" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
               </service>

我只需要提供隊列名稱

QUEUENAME=INSERT_HERE
grep ______________ $QUEUENAME. . . 

這是輸出:

Usage : xmllint [options] XMLfiles ...
   Parse the XML files and output the result of the parsing
   --version : display the version of the XML library used
   --debug : dump a debug tree of the in-memory document
   --shell : run a navigating shell
   --debugent : debug the entities defined in the document
   --copy : used to test the internal copy implementation
   --recover : output what was parsable on broken XML documents
   --noent : substitute entity references by their value
   --noout : don't output the result tree
   --path 'paths': provide a set of paths for resources
   --load-trace : print trace of all external entites loaded
   --nonet : refuse to fetch DTDs or entities over network
   --nocompact : do not generate compact text nodes
   --htmlout : output results as HTML
   --nowrap : do not put HTML doc wrapper
   --valid : validate the document in addition to std well-formed check
   --postvalid : do a posteriori validation, i.e after parsing
   --dtdvalid URL : do a posteriori validation against a given DTD
   --dtdvalidfpi FPI : same but name the DTD with a Public Identifier
   --timing : print some timings
   --output file or -o file: save to a given file
   --repeat : repeat 100 times, for timing or profiling
   --insert : ad-hoc test for valid insertions
   --compress : turn on gzip compression of output
   --html : use the HTML parser
   --xmlout : force to use the XML serializer when using --html
   --push : use the push mode of the parser
   --memory : parse from memory
   --maxmem nbbytes : limits memory allocation to nbbytes bytes
   --nowarning : do not emit warnings from parser/validator
   --noblanks : drop (ignorable?) blanks spaces
   --nocdata : replace cdata section with text nodes
   --format : reformat/reindent the input
   --encode encoding : output in the given encoding
   --dropdtd : remove the DOCTYPE of the input docs
   --c14n : save in W3C canonical format (with comments)
   --exc-c14n : save in W3C exclusive canonical format (with comments)
   --nsclean : remove redundant namespace declarations
   --testIO : test user I/O support
   --catalogs : use SGML catalogs from $SGML_CATALOG_FILES
                otherwise XML Catalogs starting from 
            file:///etc/xml/catalog are activated by default
   --nocatalogs: deactivate all catalogs
   --auto : generate a small doc on the fly
   --xinclude : do XInclude processing
   --noxincludenode : same but do not generate XInclude nodes
   --loaddtd : fetch external DTD
   --dtdattr : loaddtd + populate the tree with inherited attributes 
   --stream : use the streaming interface to process very large files
   --walker : create a reader and walk though the resulting doc
   --pattern pattern_value : test the pattern support
   --chkregister : verify the node registration code
   --relaxng schema : do RelaxNG validation against the schema
   --schema schema : do validation against the WXS schema
   --schematron schema : do validation against a schematron
   --sax1: use the old SAX1 interfaces for processing
   --sax: do not build a tree but work just at the SAX level

Libxml project home page: http://xmlsoft.org/
To report bugs or get some help check: http://xmlsoft.org/bugs.html

這是版本

xmllint: using libxml version 20626

如果你使用的是最新 ksh的——我指的是最近的版本ksh93——你實際上可以使用它。ksh93支持複合變數類型(有點像 C 結構)或 XML 節點樹。目前它本身並不支持 XML——儘管我相信它是計劃好的——但它json現在確實支持。

我使用了一些免費的線上轉換器來獲取json您的樣本輸出。儘管如此,在稍微清理一下樣本之後*(順便說一下,</connectionpools>中的****p應該是大寫的)*我可以這樣做:

print -j queue.services.[@name]

……並獲得了……

GETME

我也可以這樣做:

print -j queue.services[1].[@name]

……取而代之……

GETME2

在連結的轉換站點上,我必須選擇製表符分隔以防止它粘在很多不間斷的空間中,但除此之外,它似乎還可以。當然,您可以輕鬆地在本地使用一些工具來進行類似的轉換。

無論如何,ksh您可以json像我一樣將其複製到剪貼板後在樹中閱讀,例如:

read -m json queue &lt;&lt;&lt;"$(xsel -bo)"

之後,我可以像查看整個結構一樣…

print -j queue

…列印…

{
   "batchServices": [
       {
           "@name": "batch1",
           "executor": {
               "@className": "com.abc.xyz.qwer.qweqwewqe.ffdsdfsdfsdfsdf"
           }
       },
       {
           "@name": "batch2",
           "executor": {
               "@className": "com.abc.xyz.qwer.qweqwewqe.zxcsadsad"
           }
       }
   ],
   "configfile": "sample.xml",
   "connectionPools": [
       {
           "driver": "oracle.jdbc.driver.OracleDriver",
           "maxConnections": "10",
           "minConnections": "0",
           "name": "asdasd",
           "password": "$asdasd_PASSWORD",
           "poolUrl": "jdbc:asdsad:asdasdsad",
           "testSql": "select * from abc",
           "url": "$asdasd_URL",
           "userId": "$asdasd_USER"
       }
   ],
   "exceptionsFilterConfigFile": "asdasd.xml",
   "keyInfoConfigFile": "asdasd.xml",
   "services": [
       {
           "@backend": "ABC",
           "@idleTime": "300",
           "@max": "10",
           "@min": "1",
           "@name": "GETME",
           "handlerContainer": {
               "@className": "com.abc.xyz.wqere.abcqwere",
               "handler": {
                   "@className": "com.abc.xyz.qweqweqwe.werwerwerwer"
               }
           },
           "mqListener": {
               "@copyMessageId": "true",
               "@maxExpiry": "500",
               "@minExpiry": "4",
               "@queue": "ABC.getme",
               "@suggExpiry": "30"
           }
       },
       {
           "@backend": "ABC",
           "@idleTime": "300",
           "@max": "10",
           "@min": "1",
           "@name": "GETME2",
           "handlerContainer": {
               "@className": "com.abc.xyz.wqere.abcqwere",
               "handler": {
                   "@className": "com.abc.xyz.qweqweqwe.werwerwerwer"
               }
           },
           "mqListener": {
               "@copyMessageId": "true",
               "@maxExpiry": "500",
               "@minExpiry": "4",
               "@queue": "ABC.getme2",
               "@suggExpiry": "30"
           }
       }
   ]
}

正如上面評論中提到的,xmllint可以像這樣使用

xmllint --xpath '//service/[@name="GETME"]' Sample.xml

該選項至少從 libxml 版本 20903 開始可用。

可以在此處找到有關 xpath 語法的入門:http: //www.w3schools.com/xpath/xpath_syntax.asp或更權威的https://www.w3.org/Consortium/Offices/Presentations/XSLT_XPATH/#(23)

引用自:https://unix.stackexchange.com/questions/206895