bash 스크립트에서 노드 값을 얻기 위해 XML을 구문 분석합니까?

다음 경로로 노드의 값을 얻는 방법을 알고 싶습니다.

config/global/resources/default_setup/connection/host config/global/resources/default_setup/connection/username config/global/resources/default_setup/connection/password config/global/resources/default_setup/connection/dbname 

다음 XML에서 :

<?xml version="1.0"?> <config> <global> <install> <date><![CDATA[Tue, 11 Dec 2012 12:31:25 +0000]]></date> </install> <crypt> <key><![CDATA[70e75d7969b900b696785f2f81ecb430]]></key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db> <table_prefix><![CDATA[]]></table_prefix> </db> <default_setup> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[pass123]]></password> <dbname><![CDATA[testdb]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[pdo_mysql]]></type> <pdoType><![CDATA[]]></pdoType> <active>1</active> </connection> </default_setup> </resources> <session_save><![CDATA[files]]></session_save> </global> <admin> <routers> <adminhtml> <args> <frontName><![CDATA[admin]]></frontName> </args> </adminhtml> </routers> </admin> </config> 

또한 나중에 사용하기 위해 해당 값을 변수에 할당하고 싶습니다. 아이디어를 알려주세요.

댓글

답변

xmllint (태그로 제공됨) :

xmllint --version # xmllint: using libxml version 20703 # Note: Newer versions of libxml / xmllint have a --xpath option which # makes it possible to use xpath expressions directly as arguments. # --xpath also enables precise output in contrast to the --shell & sed approaches below. #xmllint --help 2>&1 | grep -i "xpath" 

{ # the given XML is in file.xml host="$(echo "cat /config/global/resources/default_setup/connection/host/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" username="$(echo "cat /config/global/resources/default_setup/connection/username/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" password="$(echo "cat /config/global/resources/default_setup/connection/password/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" dbname="$(echo "cat /config/global/resources/default_setup/connection/dbname/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" printf "%s\n" "host: $host" "username: $username" "password: $password" "dbname: $dbname" } # output # host: localhost # username: root # password: pass123 # dbname: testdb 

XML 문자열 만 있고 임시 파일의 사용을 피해야하는 경우 파일 설명자는 xmllint (여기에 파일 인수로 /dev/fd/3가 지정됨) :

set +H { xmlstr="<?xml version="1.0"?> <config> <global> <install> <date><![CDATA[Tue, 11 Dec 2012 12:31:25 +0000]]></date> </install> <crypt> <key><![CDATA[70e75d7969b900b696785f2f81ecb430]]></key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db> <table_prefix><![CDATA[]]></table_prefix> </db> <default_setup> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[pass123]]></password> <dbname><![CDATA[testdb]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[pdo_mysql]]></type> <pdoType><![CDATA[]]></pdoType> <active>1</active> </connection> </default_setup> </resources> <session_save><![CDATA[files]]></session_save> </global> <admin> <routers> <adminhtml> <args> <frontName><![CDATA[admin]]></frontName> </args> </adminhtml> </routers> </admin> </config> " # exec issue #exec 3<&- 3<<<"$xmlstr" #exec 3<&- 3< <(printf "%s" "$xmlstr") exec 3<&- 3<<EOF $(printf "%s" "$xmlstr") EOF { read -r host; read -r username; read -r password; read -r dbname; } < <( echo "cat /config/global/resources/default_setup/connection/*[self::host or self::username or self::password or self::dbname]/text()" | xmllint --nocdata --shell /dev/fd/3 | sed -e "1d;$d" -e "/^ *--* *$/d" ) printf "%s\n" "host: $host" "username: $username" "password: $password" "dbname: $dbname" exec 3<&- } set -H # output # host: localhost # username: root # password: pass123 # dbname: testdb 

댓글

답변

이미 많은 답변이 있지만 xml2에 대해 이야기하겠습니다.

$ xml2 < test.xml /config/global/install/date=Tue, 11 Dec 2012 12:31:25 +0000 /config/global/crypt/key=70e75d7969b900b696785f2f81ecb430 /config/global/disable_local_modules=false /config/global/resources/db/table_prefix /config/global/resources/default_setup/connection/host=localhost /config/global/resources/default_setup/connection/username=root /config/global/resources/default_setup/connection/password=pass123 /config/global/resources/default_setup/connection/dbname=testdb /config/global/resources/default_setup/connection/initStatements=SET NAMES utf8 /config/global/resources/default_setup/connection/model=mysql4 /config/global/resources/default_setup/connection/type=pdo_mysql /config/global/resources/default_setup/connection/pdoType /config/global/resources/default_setup/connection/active=1 /config/global/session_save=files /config/admin/routers/adminhtml/args/frontName=admin 

약간 마법을 사용하면 변수로 직접 설정할 수도 있습니다.

답변

xmllint -xpath 옵션을 사용하면 매우 쉽습니다. 다음과 같이 간단하게 수행 할 수 있습니다.

XML_FILE=/path/to/file.xml HOST=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/host)" $XML_FILE USERNAME=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/username)" $XML_FILE PASSWORD=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/password)" $XML_FILE DBNAME=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/dbname)" $XML_FILE 

요소의 속성을 가져와야하는 경우 XPath를 사용하는 것도 쉽습니다. 다음 파일이 있다고 가정 해보십시오.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon name="Turn Off" version="0.10.0" provider-name="Dag Wieërs"> ..snip.. </addon> 

필요한 쉘 문은 다음과 같습니다.

VERSION=$(xmllint --xpath "string(/addon/@version)" $ADDON_XML) AUTHOR=$(xmllint --xpath "string(/addon/@provider-name)" $ADDON_XML) 

답변

테스트 데이터에 대해 실행하면 다음이 작동합니다.

{ read -r host; read -r username; read -r password; read -r dbname; } \ < <(xmlstarlet sel -t -m /config/global/resources/default_setup/connection \ -v ./host -n \ -v ./username -n \ -v ./password -n \ -v ./dbname -n) 

이렇게하면 콘텐츠가 변수 host, username, password 및 .

코멘트

  • xmlstarlet : 명령을 찾을 수 없으므로이 명령은 나에게 유용하지 않습니다. : (
  • @MagePsycho bash는 XML 구문 분석을 기본적으로 지원하지 않습니다.이를 지원하는 도구 (xmlstarlet, xsltproc, 최신 Python 등)가 필요합니다. , 또는 ‘ XML을 올바르게 구문 분석 할 수 없습니다.
  • @CharlesDuffy 값을 가져 오는 방법이 정규식 패턴을 사용하는 것일 수 있습니까?
  • @MagePsycho는 xmlstarlet 만 설치할 수 있습니다. 어떤 경우에도 정규를 사용하지 마십시오. (X) HTML을 구문 분석하는 ar 표현식 .
  • @MagePsycho terdon이 이미했던 것과 동일한 링크를 게시하려고했습니다. 요약 : 아니요.

답변

순수한 bash 안타깝게도 적절한 설치가 허용되지 않은 경우에만 사용할 수 있습니다. 이것은 더 복잡한 XML에서 실패 할 수 있으며 아마도 실패 할 것입니다.

 function xmlpath() { local expr="${1//\// }" local path=() local chunk tag data while IFS="" read -r -d "<" chunk; do IFS=">" read -r tag data <<< "$chunk" case "$tag" in "?"*) ;; "!–-"*) ;; "![CDATA["*) data="${tag:8:${#tag}-10}" ;; ?*"/") ;; "/"?*) unset path[${#path[@]}-1] ;; ?*) path+=("$tag") ;; esac [[ "${path[@]}" == "$expr" ]] && echo "$data" done }  

사용 :

bash-4.1$ xmlpath "config/global/resources/default_setup/connection/host" < MagePsycho.xml localhost 

알려진 문제 :

  • 느림
  • 태그 이름으로 만 검색
  • 문자 엔티티 디코딩 없음

Answer

이 주석은 sh / bash 명령과 메서드 만 사용합니다! /test.xml은 첫 번째 질문에서 XML 유형 파일입니다 …

#!/bin/sh cat /test.xml | while read line;do [ "$(echo "$line" | grep "<host>")" ]&& echo "host: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<username>")" ]&& echo "username: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<password>")" ]&& echo "password: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<dbname")" ]&& echo "dbname: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" done 

출력 :

host: localhost username: root password: pass123 dbname: testdb 

이 값을 파일에 쓰려면 다음 방법을 사용하십시오.

#!/bin/sh cat /test.xml | while read line;do [ "$(echo "$line" | grep "<host>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/host [ "$(echo "$line" | grep "<username>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/username [ "$(echo "$line" | grep "<password>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/password [ "$(echo "$line" | grep "<dbname")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/dbname done 

이 방법은 값을 가져 오는 데만 사용되는 로컬 파일을 덮어 씁니다 (데이터 출력 파일에서 손실 됨)

Answer

bash 스크립트에서 PHP 명령 줄 인터페이스 코딩을 사용하여 여러 복잡한 작업을 처리 할 수 있습니다. 실제로 여러 줄의 코딩에 걸쳐있는 스크립트. 먼저 PHP 스크립트를 사용하여 솔루션을 만든 다음 나중에 CLI 모드를 사용하여 매개 변수를 전달합니다. 따라서 XML 파서의 뛰어난 사용을 제어 할 수 있습니다.

환경은 ssh / shell 액세스를 통해 클라이언트 모드에서 PHP를 사용할 수있는 것 같습니다.

php -f yourxmlparser.php 

이제 PHP 파일 내에서 모든 작업을 수행합니다. 사용할 수있는 명령 줄 매개 변수를 사용합니다.

반환 값을 Shell 환경에 할당하여 나머지 쉘 스크립트를 계속할 수도 있습니다.

그리고 다른 방법은 | 시간이 지남에 따라 변경되지 않는 xml 파일의 구조를 확신하는 경우 xml 파일 내에서 필요한 값과 일치하는 grep 옵션.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다