XML 명령 줄 처리를위한 Grep 및 Sed


147

쉘 스크립팅을 수행 할 때 일반적으로 데이터는 csv와 같은 단일 행 레코드 파일에 있습니다. 이와이 데이터를 처리하기 위해 정말 간단 grep하고 sed. 그러나 XML을 자주 다루어야하므로 명령 줄을 통해 해당 XML 데이터에 대한 액세스를 스크립트로 작성하는 방법을 정말로 원합니다. 가장 좋은 도구는 무엇입니까?


답변:


105

xmlstarlet이 이런 종류의 것을 꽤 잘 발견했습니다.

http://xmlstar.sourceforge.net/

대부분의 배포 저장소에서도 사용 가능해야합니다. 입문 튜토리얼은 다음과 같습니다.

http://www.ibm.com/developerworks/library/x-starlet.html


1
Sourceforge 사이트에 사용 가능한 Windows 바이너리가 있다고 생각했습니다.
Steve Bennett

내가 알 수있는 한 XQuery는 지원하지 않습니다.
Steve Bennett

@SteveBennett는 실제로는 그렇지 않지만 XPath 위에 추가되는 기능은 "grep and sed"와 경쟁하기에 충분합니다. XQuery의 훌륭하고 멋진 장점을 원한다면 perl 또는 awk와 동등한 XML과 비슷합니다. :)
Charles Duffy

36

유망한 도구 :

  • nokogiri : XPath 및 CSS 선택기를 사용하여 루비로 HTML / XML DOM 파싱

  • hpricot : 더 이상 사용되지 않음

  • fxgrep : 자체 XPath와 유사한 구문을 사용하여 문서를 쿼리합니다. SML로 작성되었으므로 설치가 어려울 수 있습니다.

  • LT XML : SGML의 포함 도구에서 파생 된 XML 툴킷 sggrep, sgsort, xmlnorm등이있다. 자체 쿼리 구문을 사용합니다. 문서는 매우 형식적입니다. LT XML 2는 XPath, XInclude 및 기타 W3C 표준을 지원한다고 주장합니다.

  • xmlgrep2 : XPath를 이용한 간단하고 강력한 검색. XML :: LibXML 및 libxml2를 사용하여 Perl로 작성되었습니다.

  • XQSharp : XPath의 확장 인 XQuery를 지원합니다. .NET Framework 용으로 작성되었습니다.

  • xml-coreutils : GNU coreutils와 동등한 Laird Breyer 툴킷. 이상적인 툴킷에 포함되어야 할 내용 에 대한 흥미로운 에세이 에서 논의했습니다 .

  • xmldiff : 두 개의 xml 파일을 비교하는 간단한 도구입니다.

  • xmltk : 데비안, 우분투, 페도라 또는 macports에 패키지가없는 것 같고 2007 년 이후 릴리스가 없었으며 이식 할 수없는 빌드 자동화를 사용합니다.

xml-coreutils는 가장 잘 문서화되고 가장 UNIX 지향적 인 것 같습니다.


1
Ruby 프로그램 용 래퍼 스크립트를 작성하고 스크립트의 인수 배열을 hpricot에 전달할 수 없습니까? 예를 들어, PHP 쉘 스크립트에서 다음과 같은 것이 작동해야합니다 : <? php / path / to / hpricot $ argv?>
alastairs

25

Joseph Holsten의 훌륭한 목록에 Perl 라이브러리 XML :: XPath와 함께 제공되는 xpath 명령 줄 스크립트를 추가합니다. XML 파일에서 정보를 추출하는 좋은 방법 :

 xpath -q -e '/entry[@xml:lang="fr"]' *xml

3
이것은 기본적으로 osx에 설치되지만 -q -e옵션 은 없습니다 . 예를 들어 "AndroidManifest.xml"의 "manifest"노드에서 "package"속성 값을 가져옵니다.xpath AndroidManifest.xml 'string(/manifest/@package)' 2> /dev/null
antonj

25

또한이 xml22xml쌍. 일반적인 문자열 편집 도구로 XML을 처리 할 수 ​​있습니다.

예. q.xml :

<?xml version="1.0"?>
<foo>
    text
    more text
    <textnode>ddd</textnode><textnode a="bv">dsss</textnode>
    <![CDATA[ asfdasdsa <foo> sdfsdfdsf <bar> ]]>
</foo>

xml2 < q.xml

/foo=
/foo=   text
/foo=   more text
/foo=   
/foo/textnode=ddd
/foo/textnode
/foo/textnode/@a=bv
/foo/textnode=dsss
/foo=
/foo=    asfdasdsa <foo> sdfsdfdsf <bar> 
/foo=

xml2 < q.xml | grep textnode | sed 's!/foo!/bar/baz!' | 2xml

<bar><baz><textnode>ddd</textnode><textnode a="bv">dsss</textnode></baz></bar>

추신 html2/도 2html있습니다.


@Joseph Holsten 예. XPath를 생각하지 않고 XML로 해킹 할 수 있습니다.
Vi.

좋은! 중간 형식을 사용하지 않는 도구에 중점을 두었지만, 충실도 높은 라인 지향 XML 표현 아이디어는 실제 grep과 sed를 계속 사용하는 좋은 방법 인 것 같습니다. pyxie를 사용해 보셨습니까? 어떻게 비교합니까? 다른 라인 지향 표현이 있습니까? xml 개행을 엔터티 (& # 10;)로 바꾸는 것보다 더 나은 방법을 고려 하시겠습니까? 이렇게하면 최소한 같은 줄에 레코드를 붙일 수 있습니다. 아, 프로젝트에 대한 링크를 포함하도록 게시물을 편집 할 수 있습니까?
Joseph Holsten

@Joseph Holsten 아니요, pyxie 형식이 xml2 형식보다 유용하다고 생각하지 않습니다. xml2는 중첩 된 XML 요소에 "전체 경로"를 제공하므로보다 라인 지향 일치 및 대체가 가능합니다. 또한 2xml부분 (필터링 된) xml2출력 에서 XML을 쉽게 다시 만들 수 있습니다 .
Vi.

5
+1 나는 이것을 충분히지지 할 수 없다 ... cat foo.xml | xml2 | grep /bar | 2xml— 원본과 같은 구조를 제공하지만, "bar"요소를 제외한 모든 요소가 제거되었다. 대박.
mogsie

14

xmllint를 사용할 수 있습니다 :

xmllint --xpath //title books.xml

대부분의 배포판과 함께 번들로 제공되며 Cygwin과 함께 번들로 제공됩니다.

$ xmllint --version
xmllint: using libxml version 20900

보다:

$ xmllint
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
        ...
        --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
        --oldxml10: use XML-1.0 parsing rules before the 5th edition
        --xpath expr: evaluate the XPath expression, inply --noout

2
더 없다 --xpath에 인수 xmllint: manpagez.com/man/1/xmllint
비참한 변수

1
@MiserableVariable : 매뉴얼 페이지가 올바르지 않습니다. 방금 설명서의 맨 페이지를 보았습니다. xpath 인수가 나열되지 않았습니다. 이것은 문서 오류입니다. 대신 프로그램을 실행하십시오.
Dave Jarvis

2
@MiserableVariable --xpath은 최근에 추가 된 것으로 RHEL 6 버전에는 없습니다 xmllint.
Daniel Beck

2
보다 정확하게 xmllint --xpath는 libxml2 2.7.7 (2010 년)에 도입되었습니다.
marbu

9

Windows에서 솔루션을 찾고 있다면 Powershell에는 XML을 읽고 쓰는 기능이 내장되어 있습니다.

test.xml :

<root>
  <one>I like applesauce</one>
  <two>You sure bet I do!</two>
</root>

Powershell 스크립트 :

# load XML file into local variable and cast as XML type.
$doc = [xml](Get-Content ./test.xml)

$doc.root.one                                   #echoes "I like applesauce"
$doc.root.one = "Who doesn't like applesauce?"  #replace inner text of <one> node

# create new node...
$newNode = $doc.CreateElement("three")
$newNode.set_InnerText("And don't you forget it!")

# ...and position it in the hierarchy
$doc.root.AppendChild($newNode)

# write results to disk
$doc.save("./testNew.xml")

testNew.xml :

<root>
  <one>Who likes applesauce?</one>
  <two>You sure bet I do!</two>
  <three>And don't you forget it!</three>
</root>

출처 : /server/26976/update-xml-from-the-command-line-windows


Powershell에 의지하기 전에 몇 시간 동안 다양한 Linux 도구와 싸웠습니다. 나는 이것이 너무 어렵다는 것에 놀랐다. 리눅스 cmd-line은 일반적으로 정말 좋지만 여기에 구멍이있는 것 같습니다. 참고 : 사용 사례는 다음과 같습니다. 1) xpath로 노드 찾기, 2) 발견 된 경우 제거, 3) 새 노드 추가, 4) 파일 저장. 나는 많은 solr 구성을 업데이트하고있었습니다. 사람이 할 수있는 쉬운 / 신뢰할 수있는 방법을 알고 있다면 나는 모든 귀 해요
리처드 하우어

와우, 이것은 실제로 수용 가능한 솔루션의 라인에 도달합니다. 그러나 솔직히 말해서 xps $doc .root.one xps $doc 'AppendChild("three")'and 처럼 보이면 아마도 그것을 받아 들일 것입니다 xps $doc '.three.set_InnerText("And don't you forget it!")'.
Joseph Holsten



4

saxon-lintXPath 3.0 / XQuery 3.0을 사용할 수있는 기능이있는 명령 줄 있습니다 . 다른 명령 줄 도구는 XPath 1.0을 사용합니다.

예 :

http / html :

$ saxon-lint --html --xpath 'count(//a)' http://stackoverflow.com/q/91791
328

xml :

$ saxon-lint --xpath '//a[@class="x"]' file.xml


3

XQuery는 좋은 솔루션 일 수 있습니다. 배우기 쉽고 (상대적으로) W3C 표준입니다.

커맨드 라인 프로세서에 XQSharp 를 권장 합니다 .


1
BaseX에는 데이터베이스 모드 외에도 명령 줄 XQuery 프로세서가 있으며 최신 버전의 표준을 사용하여 최신 상태를 유지합니다 (XQuery 3.0의 초안을 매우 밀접하게 준수).
Charles Duffy


1

그렙 동등 물

python3 코드를 감싸는 "xp"( "xpath")와 같은 bash 함수를 정의 할 수 있습니다. 그것을 사용하려면 python3 및 python-lxml을 설치해야합니다. 혜택:

  1. xmllint에서 부족한 정규식 일치.
  2. 명령 행에서 파이프로 필터로 사용

다음과 같이 사용하는 것이 쉽고 강력합니다.

xmldoc=$(cat <<EOF
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
EOF
)
selection='//*[namespace-uri()="http://www.sample.com/" and local-name()="job" and re:test(.,"^pro.*ing$")]/text()'
echo "$xmldoc" | xp "$selection"
# prints programming

xp ()는 다음과 같습니다 :

xp()
{ 
local selection="$1";
local xmldoc;
if ! [[ -t 0 ]]; then
    read -rd '' xmldoc;
else
    xmldoc="$2";
fi;
python3 <(printf '%b' "from lxml.html import tostring\nfrom lxml import etree\nfrom sys import stdin\nregexpNS = \"http://exslt.org/regular-expressions\"\ntree = etree.parse(stdin)\nfor e in tree.xpath('""$selection""', namespaces={'re':regexpNS}):\n  if isinstance(e, str):\n    print(e)\n  else:\n    print(tostring(e).decode('UTF-8'))") <<< "$xmldoc"
}

sed 상당

jq "프로그래밍 언어"의 모든 기능을 제공하는 xq 사용을 고려하십시오. python-pip가 설치된 경우 pip install yq로 xq를 설치할 수 있습니다 . 아래 예에서는 "계정 유지"를 "계정 유지 2"로 바꾸고 있습니다.

xmldoc=$(cat <<'EOF'
<resources>
    <string name="app_name">Keep Accounts</string>
    <string name="login">"login"</string>
    <string name="login_password">"password:"</string>
    <string name="login_account_hint">input to login</string>
    <string name="login_password_hint">input your password</string>
    <string name="login_fail">login failed</string>
</resources>
EOF
)
echo "$xmldoc" | xq '.resources.string = ([.resources.string[]|select(."#text" == "Keep Accounts") ."#text" = "Keep Accounts 2"])' -x

-1

JEdit에는 "XQuery"라는 플러그인이 있으며 XML 문서에 대한 쿼리 기능을 제공합니다.

커맨드 라인은 아니지만 작동합니다!


JEdit에는 파일을 검색 할 수있는 방법이 있지만 경쟁사와는 다릅니다 grep(1).
Joseph Holsten
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.