ksh의 키워드를 사용하여 xml 파일에서 xml 청크를 grep하는 방법

ksh의 키워드를 사용하여 xml 파일에서 xml 청크를 grep하는 방법

많은 서비스가 포함된 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>

다음과 같이 XML 덩어리를 grep해야 합니다.

 <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

답변1

당신이 사용하는 경우최신 ksh- 가장 최신 버전을 의미합니다 ksh93. 실제로 사용할 수 있습니다. ksh93지원하다화합물변수 유형(C 구조체와 같은 종류) 또는 XML 노드 트리. 현재는 기본적으로 XML을 지원하지 않습니다. 비록 그것이 계획되어 있다고 확신하지만, json지금은 지원합니다.

나는 일부를 사용했다무료 온라인 변환기json샘플 출력을 얻기 위한 것입니다. 그럼에도 불구하고 샘플을 약간 정리한 후(이것존재하다</연결 풀>참고로 대문자로 해야함)나는 그것을 할 수 있다:

print -j queue.services.[@name]

...그리고 보상을 받으세요...

GETME

나는 또한 이것을 할 수 있습니다 :

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

...대신에...

GETME2

연결된 전환 사이트에서 선택해야 합니다.탭으로 구분됨방해받지 않는 공간이 많이 붙는 것을 방지하기 위한 것 외에는 괜찮은 것 같습니다. 물론 유사한 변환을 수행하기 위해 로컬에서 쉽게 사용할 수 있는 도구가 있습니다.

어쨌든, 제가 했던 것처럼 클립보드에 복사한 후 ksh트리에서 읽을 수 있습니다. 예를 들면 다음과 같습니다.json

read -m json queue <<<"$(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"
            }
        }
    ]
}

답변2

위의 댓글에서 언급했듯이 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)

답변3

자격 있는:

  1. 읽기 전용 권한이 없기 때문에 XML 파서 도구를 사용할 수 없습니다.

  2. 내 버전의 xmllint는 xpath를 지원하지 않습니다. 업데이트할 수 없으며 읽기 전용입니다.

  3. xmlstarlet이 없어서 설치할 수 없습니다.

나는 다른 비전통적인 해결책을 찾는 데 의지했습니다. 이 awk 명령은 내 요구 사항을 충족합니다.

awk '
  /<service.*name=/ { f=1 ; m=0 ; res="" }
  f { res = res $0 ORS }
  f && /mqListener queue="ABC.getme2"/ { m=1 }
  /<\/service>/ { f=0 ; if (m) print res $0 }
' Sample.xml

여기에서 나를 도와준 @Janis에게 특별히 감사드립니다.입력 매개변수가 블록 중간에 있을 때 xml 블록을 가져올 때 awk 범위 모드를 구현하는 방법

답변4

무엇보다도 grepXML은 정규식 기반 구문 분석에 적합한 형식이 아닙니다. 대신 XML 파서를 사용하세요.

내가 가장 좋아하는 XML 파서는 실제로 perl다음과 같은 프로그램 입니다.XML::Twig.

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my ($keyword, $filename) = @ARGV;

XML::Twig->new(
    'pretty_print'  => 'indented_a',
    'twig_handlers' => {
        'service[@name="'.$keyword.'"]' => sub { $_->print }
    }
)->parsefile($filename);

호출하면 myscript.pl GETME yourxml일치하는 항목이 모두 인쇄됩니다. ( pretty_print원하는 형식으로 변경하세요.)

XML::Twig실제로 여러 가지 예제 사용 사례도 함께 번들로 제공되므로 xml_grep예를 들어 원하는 작업을 많이 수행할 수 있습니다.

위의 예제 XML 사용(작동하지 않으므로 약간 수정됨)추정소스 XML은 실제로 다음과 같습니다. 이는 전치 오류입니다.

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

참고: 이 형식 indented_aXML::Twig기타 형식을 사용할 수 있습니다. 이것이 정규식과 줄 기반 XML 일치가 위험한 이유 중 적어도 일부입니다.

관련 정보