বাশ স্ক্রিপ্টে নোড মান পেতে পার্স এক্সএমএল?


19

আমি জানতে চাই যে কীভাবে আমি নীচের পথগুলি সহ নোডের মান পেতে পারি:

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 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>

এছাড়াও আমি আরও ব্যবহারের জন্য ভেরিয়েবলের জন্য সেই মানটি নির্ধারণ করতে চাই। আমাকে আপনার ধারণা জানাতে।


7
স্বেচ্ছাসেবী তথ্যের কাঠামোগত গাছগুলি পার্স করতে কখনও ব্যাশ ব্যবহার করবেন না। একটি আসল এক্সএমএল পার্সার ব্যবহার করুন। আমি এক্সএমএল স্টারলেট সুপারিশ ।
ক্রিস ডাউন

উত্তর:


19

ব্যবহার bashএবং 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

যদি কেবল একটি এক্সএমএল স্ট্রিং থাকে এবং একটি অস্থায়ী ফাইলের ব্যবহার এড়ানো যায়, ফাইল বর্ণনাকারীদের সাথে যাওয়ার উপায় 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

1
ম্যান পৃষ্ঠা: xmlsoft.org/xmllint.html
জেসন পায়ারন

6

যদিও এর মধ্যে ইতিমধ্যে প্রচুর উত্তর রয়েছে, তবে আমি এতে চিমিয়ে দেব 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

সামান্য যাদু দ্বারা আপনি এগুলি সরাসরি ভেরিয়েবল হিসাবে সেট করতে পারেন:

$ eval $(xml2 < test.xml | tr '/, ' '___' | grep =)
$ echo $_config_global_resources_default_setup_connection_host          
localhost

3

আপনার পরীক্ষার ডেটার বিপরীতে চালানোর সময় নিম্নলিখিতটি কাজ করে:

{ 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এবং dbname


xMLstarlet: কমান্ড পাওয়া যায় নি, সুতরাং এই আদেশটি আমার পক্ষে কার্যকর নয় :(
ম্যাজপাইকো

@ ম্যাজপাইকো এক্সএমএল পার্সিংয়ের জন্য bashকোনও অন্তর্নির্মিত সমর্থন নেই। হয় আপনার কাছে এমন একটি সরঞ্জাম থাকা দরকার যা (xMLstarlet, xsltproc, একটি আধুনিক পাইথন, ইত্যাদি) করে বা আপনি XML সঠিকভাবে পার্স করতে পারবেন না।
চার্লস ডাফি

@ চার্লসডাফি কি রেগেক্স প্যাটার্নটি ব্যবহার করতে পারে মানটি পাওয়ার কোনও উপায় আছে?
ম্যাজপাইকো

5
@ ম্যাজপাইকো আপনি কেবল এক্সএমএল স্টারলেট ইনস্টল করতে পারেন। যে কোনও ক্ষেত্রে, আপনার কখনই (এক্স) এইচটিএমএল পার্স করার জন্য নিয়মিত এক্সপ্রেশন ব্যবহার করা উচিত নয়
টেরডন

1
@ ম্যাজপাইকো আমি ইতিমধ্যে টার্মন একই লিঙ্কটি পোস্ট করতে চলেছি। সংক্ষেপে: না
চার্লস ডাফি

3

একটি খাঁটি bashফাংশন, দুর্ভাগ্যজনক ক্ষেত্রে কেবল যখন আপনাকে উপযুক্ত কিছু ইনস্টল করার অনুমতি দেওয়া হয় না। এটি আরও জটিল এক্সএমএলে ব্যর্থ হতে পারে এবং সম্ভবত:

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

জ্ঞাত সমস্যা:

  • ধীর
  • শুধুমাত্র ট্যাগের নাম অনুসারে অনুসন্ধান করে
  • কোন অক্ষর সত্তা ডিকোডিং

2

ব্যবহার 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

আপনার যদি কোনও উপাদানটির বৈশিষ্ট্যটি পেতে প্রয়োজন হয় তবে এটি এক্সপথ ব্যবহার করাও সহজ। আপনার কাছে ফাইলটি কল্পনা করুন:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="screensaver.turnoff"
       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)

0

আপনি কোডিংয়ের একাধিক লাইনে বিস্তৃত বেশ কয়েকটি জটিল স্ক্রিপ্টগুলি পরিচালনা করতে ব্যাশ স্ক্রিপ্টগুলিতে পিএইচপি কমান্ড লাইন ইন্টারফেস কোডিং ব্যবহার করতে পারেন। প্রথমে পিএইচপি স্ক্রিপ্টগুলি ব্যবহার করে আপনার সমাধানটি করার চেষ্টা করুন এবং তারপরে সিএলআই মোড ব্যবহার করে প্যারামিটারগুলি পাস করুন। সুতরাং, আপনি এক্সএমএল পার্সারগুলির দুর্দান্ত ব্যবহারগুলির উপর নিয়ন্ত্রণ পেতে পারেন।

পরিবেশটি মনে হচ্ছে আপনি ssh / শেল অ্যাক্সেসের মাধ্যমে ক্লায়েন্ট মোডে পিএইচপি ব্যবহার করতে পারেন।

php -f yourxmlparser.php

এখন, আপনার পিএইচপি ফাইলের মধ্যে সমস্ত জিনিস করুন। কমান্ড লাইন প্যারামিটারগুলি নিতে পারে তা ব্যবহার করুন।

এমনকি আপনার অবশিষ্ট শেল স্ক্রিপ্টগুলি চালিয়ে যাওয়ার জন্য শেল পরিবেশে সেই রিটার্ন মানগুলি নির্ধারণ করতে পারেন।

এবং অন্য উপায়টি হল x x ফাইলের মধ্যে আপনার প্রয়োজনীয় মানটির সাথে | গ্রেপ বিকল্পটি ব্যবহার করা, যদি আপনি সময়ের সাথে পরিবর্তিত হয় না এমন আপনার এক্সএমএল ফাইলের কাঠামো সম্পর্কে বেশ নিশ্চিত হন।


0

এই মন্তব্যটি কেবল sh / bash আদেশ এবং পদ্ধতি ব্যবহার করে! /test.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

এই পদ্ধতিটি আপনার স্থানীয় ফাইলগুলিকে কেবল মূল্য পেতে ব্যবহৃত ওভাররাইট করবে (আপনার ডাটাগুলি আউটপুট ফাইল থেকে হারিয়ে যাবে)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.