বাশে এক্সএমএলকে কীভাবে পার্স করবেন?


134

আদর্শভাবে, আমি যা করতে সক্ষম হতে চাই তা হ'ল:

cat xhtmlfile.xhtml |
getElementViaXPath --path='/html/head/title' |
sed -e 's%(^<title>|</title>$)%%g' > titleOfXHTMLPage.txt

উত্তর:


153

এটি সত্যই ইউজেমের উত্তরের ব্যাখ্যা মাত্র , তবে আমি মনে করি না যে এত বেশি সম্পাদনা অন্য কারও সাথে করা উচিত, এবং মন্তব্যগুলি বিন্যাসের অনুমতি দেয় না, তাই ...

rdom () { local IFS=\> ; read -d \< E C ;}

আসুন "আরডিএম" এর পরিবর্তে "রিড_ডম" কল করুন, এটিকে কিছুটা ফাঁক করুন এবং দীর্ঘতর ভেরিয়েবলগুলি ব্যবহার করুন:

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
}

ঠিক আছে সুতরাং এটি একটি ফাংশন সংজ্ঞা দেয় যা রিড_ডম বলে। প্রথম লাইনটি এই ফাংশনে আইএফএসকে (ইনপুট ফিল্ড বিভাজক) স্থানীয় করে এবং এটিতে পরিবর্তন করে। এর অর্থ এই যে আপনি স্থান, ট্যাব বা নিউলাইনগুলিতে স্বয়ংক্রিয়ভাবে বিভক্ত হওয়ার পরিবর্তে ডেটা পড়লে এটি '>' এ বিভক্ত হয়। পরের লাইনটি স্টিডিনের ইনপুট পড়তে বলেছে এবং নতুন লাইনে থামার পরিবর্তে আপনি যখন একটি '<' অক্ষর দেখতে পাচ্ছেন তখনই থামুন ( যা পড়া হয় তা আইএফএস ব্যবহার করে বিভক্ত হয় এবং ভেরিয়েবল ENTITY এবং বিষয়বস্তুতে নির্ধারিত হয়। সুতরাং নিম্নলিখিত নিন:

<tag>value</tag>

read_domখালি স্ট্রিং পেতে প্রথম কল (যেহেতু '<' প্রথম অক্ষর)। এটি আইএফএস দ্বারা কেবল '' তে বিভক্ত হয়ে যায়, কারণ '>' অক্ষর নেই। পড়ুন তারপর উভয় ভেরিয়েবলের একটি খালি স্ট্রিং বরাদ্দ করে। দ্বিতীয় কলটিতে স্ট্রিংটি 'ট্যাগ> মান' পায়। এরপরে আইএফএস দ্বারা বিভক্ত হয়ে যায় দুটি ক্ষেত্র 'ট্যাগ' এবং 'মান' into পড়ুন তারপর ভেরিয়েবলগুলি যেমন: ENTITY=tagএবং এর জন্য নির্ধারিত করে CONTENT=value। তৃতীয় কলটি স্ট্রিং '/ ট্যাগ>' পায়। এটি আইএফএস দ্বারা দুটি ক্ষেত্র '/ ট্যাগ' এবং '' এ বিভক্ত হয়। পড়ুন তারপর ভেরিয়েবলগুলি যেমন: ENTITY=/tagএবং এর জন্য নির্ধারিত করে CONTENT=। চতুর্থ কলটি শূন্য নয় এমন স্থিতি ফিরে আসবে কারণ আমরা ফাইলের শেষে পৌঁছেছি।

উপরের সাথে মেলে এখন তার লুপটি কিছুটা পরিষ্কার করেছে:

while read_dom; do
    if [[ $ENTITY = "title" ]]; then
        echo $CONTENT
        exit
    fi
done < xhtmlfile.xhtml > titleOfXHTMLPage.txt

প্রথম লাইনটি কেবল বলেছে, "যখন পাঠ_দমন শূন্য স্থিতি সঞ্চালন করে, নিম্নলিখিতটি করুন।" দ্বিতীয় সারিটি সন্ধান করে যে সত্ত্বাটি আমরা সবেমাত্র দেখেছি "শিরোনাম" is পরবর্তী পংক্তিতে ট্যাগের সামগ্রী প্রতিধ্বনিত হয়। চার লাইন প্রস্থান। যদি এটি শিরোনাম সত্তা না হয় তবে লুপটি ষষ্ঠ লাইনে পুনরাবৃত্তি করবে। আমরা "xhtmlfile.xhtml" কে স্ট্যান্ডার্ড ইনপুট ( read_domফাংশনটির জন্য) এ পুনঃনির্দেশ করি এবং স্ট্যান্ডার্ড আউটপুটটিকে "টাইটেলঅফএক্সএইচটিএমএলপেজ.টেক্সট" (লুপের আগের থেকে প্রতিধ্বনি)) এ পুনঃনির্দেশ করি।

এখন নিম্নলিখিতটি দেওয়া হয়েছে (এস 3 তে বালতি তালিকাবদ্ধকরণ থেকে আপনি কী পান) এর জন্য input.xml:

<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Name>sth-items</Name>
  <IsTruncated>false</IsTruncated>
  <Contents>
    <Key>item-apple-iso@2x.png</Key>
    <LastModified>2011-07-25T22:23:04.000Z</LastModified>
    <ETag>&quot;0032a28286680abee71aed5d059c6a09&quot;</ETag>
    <Size>1785</Size>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
</ListBucketResult>

এবং নিম্নলিখিত লুপ:

while read_dom; do
    echo "$ENTITY => $CONTENT"
done < input.xml

আপনি পাওয়া উচিত:

 => 
ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/" => 
Name => sth-items
/Name => 
IsTruncated => false
/IsTruncated => 
Contents => 
Key => item-apple-iso@2x.png
/Key => 
LastModified => 2011-07-25T22:23:04.000Z
/LastModified => 
ETag => &quot;0032a28286680abee71aed5d059c6a09&quot;
/ETag => 
Size => 1785
/Size => 
StorageClass => STANDARD
/StorageClass => 
/Contents => 

সুতরাং আমরা যদি whileইউজেমের মতো লুপ লিখি:

while read_dom; do
    if [[ $ENTITY = "Key" ]] ; then
        echo $CONTENT
    fi
done < input.xml

আমরা এস 3 বালতির সমস্ত ফাইলের একটি তালিকা পেতে চাই।

সম্পাদনা করুন যদি কোনও কারণে আপনার local IFS=\>পক্ষে কাজ না করে এবং আপনি বিশ্বব্যাপী সেট করে থাকেন তবে আপনার ফাংশন শেষে এটি পুনরায় সেট করা উচিত যেমন:

read_dom () {
    ORIGINAL_IFS=$IFS
    IFS=\>
    read -d \< ENTITY CONTENT
    IFS=$ORIGINAL_IFS
}

অন্যথায়, স্ক্রিপ্টের পরে আপনি যে কোনও লাইন বিভক্ত করবেন তা গণ্ডগোল হবে।

সম্পাদনা 2 বৈশিষ্ট্যটির নাম / মান জোড়া ভাগ করার জন্য আপনি এই read_dom()জাতীয় সংযোজন করতে পারেন:

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
    local ret=$?
    TAG_NAME=${ENTITY%% *}
    ATTRIBUTES=${ENTITY#* }
    return $ret
}

তারপরে পার্স করার জন্য আপনার ফাংশনটি লিখুন এবং আপনার পছন্দ মতো ডেটা পান:

parse_dom () {
    if [[ $TAG_NAME = "foo" ]] ; then
        eval local $ATTRIBUTES
        echo "foo size is: $size"
    elif [[ $TAG_NAME = "bar" ]] ; then
        eval local $ATTRIBUTES
        echo "bar type is: $type"
    fi
}

তারপরে আপনি যখন read_domফোন করবেন parse_dom:

while read_dom; do
    parse_dom
done

তারপরে নিচের উদাহরণটি মার্কআপ দেওয়া হয়েছে:

<example>
  <bar size="bar_size" type="metal">bars content</bar>
  <foo size="1789" type="unknown">foos content</foo>
</example>

আপনার এই আউটপুটটি পাওয়া উচিত:

$ cat example.xml | ./bash_xml.sh 
bar type is: metal
foo size is: 1789

সম্পাদনা 3 জন অন্য ব্যবহারকারী বলেছেন যে তারা এটিকে ফ্রিবিএসডি-তে সমস্যা করে এবং প্রস্থান স্থিতিটি পড়তে বাঁচাতে এবং পঠন-দফার শেষে এটি ফেরত দেওয়ার পরামর্শ দিয়েছিল:

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
    local RET=$?
    TAG_NAME=${ENTITY%% *}
    ATTRIBUTES=${ENTITY#* }
    return $RET
}

এটি কাজ না করার কোনও কারণ আমি দেখছি না


2
আপনি যদি আইএফএসকে (ইনপুট ফিল্ড বিভাজক) বিশ্বব্যাপী করেন তবে আপনার এটিকে শেষে এটির মূল মানটিতে পুনরায় সেট করা উচিত, আমি উত্তরটি সম্পাদনা করে তা পেয়েছি। অন্যথায় আপনার স্ক্রিপ্টের পরে আপনি যে কোনও অন্য ইনপুট বিভক্ত করবেন তা গণ্ডগোল হবে। আমার সন্দেহ হয় যে স্থানীয় আপনার পক্ষে কাজ না করার কারণ হ'ল হয় আপনি একটি সামঞ্জস্যতা মোডে ব্যাশ ব্যবহার করছেন (যেমন আপনার শাবংটি #! / বিন / শ) হয় বা এটি বাশের একটি প্রাচীন সংস্করণ।
চাদ

30
আপনি কেবল নিজের পার্সার লিখতে পারেন, তার অর্থ এই নয় যে আপনার উচিত।
স্টিফেন নিডজিয়েলস্কি

1
@chad এটা অবশ্যই ডেস্কটপ AWS 'কর্মপ্রবাহ / বাস্তবায়ন সম্পর্কে এমন কিছু বিষয় যা আমিও করতে "ব্যাশ XML" একটি উত্তর অনুসন্ধানের জন্য ছিল বলে wget একটি এস 3 বালতি বিষয়বস্তু!
অ্যালাস্টার

2
@ অ্যালিস্টায়ার github.com/chad3814/s3 স্ক্রিপ্টগুলি ব্যাশ স্ক্রিপ্টগুলির একটি সেটের জন্য দেখুন যা আমরা এস 3 অবজেক্টগুলিকে পরিচালনা করতে ব্যবহার করি
চাদ

5
স্থানীয় চলকটিতে আইএফএস নির্ধারণ করা ভঙ্গুর এবং প্রয়োজনীয় নয় not কেবলমাত্র করুন: IFS=\< read ...যা কেবলমাত্র পঠিত কলের জন্য আইএফএস সেট করবে। (দ্রষ্টব্য যে আমি readকোনওভাবেই এক্সএমএলকে বিশ্লেষণ করার অভ্যাসটির পক্ষে সমর্থন করছি না এবং আমি বিশ্বাস করি যে এটি করা বিপদ পূর্ণ এবং এড়ানো উচিত।)
উইলিয়াম পার্সেল

64

আপনি কেবলমাত্র ব্যাশ ব্যবহার করে এটি খুব সহজেই করতে পারেন। আপনাকে কেবল এই ফাংশনটি যুক্ত করতে হবে:

rdom () { local IFS=\> ; read -d \< E C ;}

এখন আপনি পড়ার মতো রডম ব্যবহার করতে পারেন তবে এইচটিএমএল নথির জন্য। যখন rdom বলা হয় তখন উপাদানটি ভেরিয়েবল E এবং কনটেন্টটি ভেরি সিতে বরাদ্দ করবে

উদাহরণস্বরূপ, আপনি যা করতে চেয়েছিলেন তা করতে:

while rdom; do
    if [[ $E = title ]]; then
        echo $C
        exit
    fi
done < xhtmlfile.xhtml > titleOfXHTMLPage.txt

আপনি এই সম্পর্কে বিস্তারিত বলতে পারেন? আমি বাজি দেব যে এটি আপনার কাছে পুরোপুরি স্পষ্ট .. এবং এটি একটি দুর্দান্ত উত্তর হতে পারে - যদি আপনি সেখানে কী করছেন তা যদি বলতে পারি .. আপনি কি আরও কিছুটা ভেঙে ফেলতে পারেন, সম্ভবত কিছু নমুনা আউটপুট তৈরি করে?
অ্যালেক্স গ্রে

1
আসল প্রতি ক্রেডিট - এই ওয়ান-লাইনারটি এত ফ্রিকিন 'মার্জিত এবং আশ্চর্যজনক।
ম্যাভেরিক

1
দুর্দান্ত হ্যাক, তবে শেল সম্প্রসারণ এবং শেষ লাইনের সঠিক ব্যাখ্যা (এনকন্ডিংয়ের উপর নির্ভর করে) রোধ করতে আমাকে ইকো "$ সি" এর মতো ডাবল কোট ব্যবহার করতে হয়েছিল
ইউজার 311174

8
এক্সপিএমএলকে গ্রেপ এবং অজকের সাথে পার্স করা ঠিক নয় । এক্সএমএলগুলি যথেষ্ট সহজ এবং আপনার খুব বেশি সময় না থাকলে এটি কোনও গ্রহণযোগ্য আপস হতে পারে, তবে এটি কখনও ভাল সমাধান হিসাবে বলা যায় না।
পিটারহ - মনিকা পুনরায় ইনস্টল করুন

59

কমান্ড-লাইন সরঞ্জামগুলিকে শেল স্ক্রিপ্ট থেকে কল করা যেতে পারে:

  • 4 এক্সপ্যাথ - পাইথনের 4 স্যুট প্যাকেজটির চারপাশে কমান্ড-লাইন মোড়ক
  • XMLStarlet
  • এক্সপথ - পার্লের এক্সপথ লাইব্রেরির চারপাশে কমান্ড-লাইন মোড়ক
  • জিডেল - ইউআরএল পাশাপাশি ফাইলগুলির সাথে কাজ করে। জেএসওএন-এর সাথেও কাজ করে

কমান্ড লাইন থেকে বা শেল স্ক্রিপ্টগুলিতে এক্সএমএল প্রসেসিং করতে আমি এক্সএমএলিন্ট এবং এক্সস্লটপ্রোকটি সামান্য এক্সএসএল ট্রান্সফর্ম স্ক্রিপ্টগুলি ব্যবহার করি।


2
আমি কোথা থেকে 'এক্সপথ' বা '4 এক্সপ্যাথ' ডাউনলোড করতে পারি?
ওফার

3
হ্যাঁ, দ্বিতীয় ভোট / অনুরোধ - এই সরঞ্জামগুলি কোথায় ডাউনলোড করতে হবে, বা আপনার অর্থ হ'ল একজনকে নিজে নিজে একটি র‌্যাপার লিখতে হবে? আমি বরং প্রয়োজন ব্যতিরেকে সময় নষ্ট করব না।
ডেভিড

4
sudo apt-get libxML-xpath-perl ইনস্টল করুন
অ্যান্ড্রু ওয়াগনার

22

আপনি এক্সপথ ইউটিলিটি ব্যবহার করতে পারেন। এটি পার্ল এক্সএমএল-এক্সপাথ প্যাকেজ সহ ইনস্টল করা হয়েছে।

ব্যবহার:

/usr/bin/xpath [filename] query

বা এক্সএমএল স্টারলেট । এটি মুক্ত ব্যবহারে ইনস্টল করতে:

sudo zypper install xmlstarlet

অথবা cnf xmlঅন্য প্ল্যাটফর্মগুলিতে চেষ্টা করুন।


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

অনেক সিস্টেমে, xpathযা পূর্বনির্ধারিত আসে স্ক্রিপ্টগুলির উপাদান হিসাবে ব্যবহারের জন্য অনুপযুক্ত। সম্প্রসারণের জন্য উদাহরণস্বরূপ stackoverflow.com/questions/15461737/… দেখুন ।
ট্রিপলি

2
উবুন্টু / ডেবিয়ানapt-get install xmlstarlet
রুবো 77


5

পরীক্ষা করে দেখুন XML2 থেকে http://www.ofb.net/~egnor/xml2/ যা একটি লাইন ভিত্তিক ফর্ম্যাটে এক্সএমএল পরিবর্তন করে।


5

চ্যাডের উত্তর থেকে শুরু করে, এখানে ইউএমএল পার্স করার সম্পূর্ণ কার্যনির্বাহী সমাধান রয়েছে, মাত্র 2 টি ছোট ফাংশন সহ (2 টিরও বেশি বিউ আপনি সমস্তটি মিশ্রিত করতে পারেন) সাথে মন্তব্যগুলির প্রপার হ্যান্ডলিং সহ ML আমি বলি না যে চাদ এর কোনওটিই কাজ করে না, তবে এটির সাথে খারাপভাবে গঠন করা এক্সএমএল ফাইলগুলি নিয়ে অনেক সমস্যা ছিল: সুতরাং আপনাকে মন্তব্য এবং ভুল জায়গায় স্থান / সিআর / ট্যাব / ইত্যাদি পরিচালনা করতে কিছুটা জটিল হতে হবে।

এই উত্তরের উদ্দেশ্য হ'ল পার্ল, পাইথন বা অন্য যে কোনও কিছুই ব্যবহার করে জটিল সরঞ্জাম ছাড়াই ইউএমএল পার্সিংয়ের প্রয়োজনবোধে বাক্স ব্যাশ ফাংশনগুলির বাইরে বক্স-ব্যাশ ফাংশন। আমার হিসাবে, আমি পুরানো প্রোডাকশন ওএস-এর জন্য সিপিএন ইনস্টল করতে পারছি না এবং পার্ল মডিউলগুলিও পাইনি এবং পাইথন পাওয়া যায় না।

প্রথমত, এই পোস্টে ব্যবহৃত ইউএমএল শব্দের একটি সংজ্ঞা:

<!-- comment... -->
<tag attribute="value">content...</tag>

সম্পাদনা: হ্যান্ডেল সহ আপডেট ফাংশন:

  • ওয়েবসাইটস্ফিয়ার এক্সএমএল (এক্সএমআই এবং এক্সএমএলএন বৈশিষ্ট্য)
  • 256 রঙের সাথে একটি সামঞ্জস্যপূর্ণ টার্মিনাল থাকতে হবে
  • ধূসর 24 শেড
  • IBM AIX ব্যাশ 3.2.16 (1) এর জন্য সামঞ্জস্যতা যুক্ত করা হয়েছে

ফাংশনগুলি হ'ল প্রথমে xML_read_dom যা xML_read দ্বারা পুনরাবৃত্তভাবে বলা হয়:

xml_read_dom() {
# /programming/893585/how-to-parse-xml-in-bash
local ENTITY IFS=\>
if $ITSACOMMENT; then
  read -d \< COMMENTS
  COMMENTS="$(rtrim "${COMMENTS}")"
  return 0
else
  read -d \< ENTITY CONTENT
  CR=$?
  [ "x${ENTITY:0:1}x" == "x/x" ] && return 0
  TAG_NAME=${ENTITY%%[[:space:]]*}
  [ "x${TAG_NAME}x" == "x?xmlx" ] && TAG_NAME=xml
  TAG_NAME=${TAG_NAME%%:*}
  ATTRIBUTES=${ENTITY#*[[:space:]]}
  ATTRIBUTES="${ATTRIBUTES//xmi:/}"
  ATTRIBUTES="${ATTRIBUTES//xmlns:/}"
fi

# when comments sticks to !-- :
[ "x${TAG_NAME:0:3}x" == "x!--x" ] && COMMENTS="${TAG_NAME:3} ${ATTRIBUTES}" && ITSACOMMENT=true && return 0

# http://tldp.org/LDP/abs/html/string-manipulation.html
# INFO: oh wait it doesn't work on IBM AIX bash 3.2.16(1):
# [ "x${ATTRIBUTES:(-1):1}x" == "x/x" -o "x${ATTRIBUTES:(-1):1}x" == "x?x" ] && ATTRIBUTES="${ATTRIBUTES:0:(-1)}"
[ "x${ATTRIBUTES:${#ATTRIBUTES} -1:1}x" == "x/x" -o "x${ATTRIBUTES:${#ATTRIBUTES} -1:1}x" == "x?x" ] && ATTRIBUTES="${ATTRIBUTES:0:${#ATTRIBUTES} -1}"
return $CR
}

এবং দ্বিতীয়টি:

xml_read() {
# /programming/893585/how-to-parse-xml-in-bash
ITSACOMMENT=false
local MULTIPLE_ATTR LIGHT FORCE_PRINT XAPPLY XCOMMAND XATTRIBUTE GETCONTENT fileXml tag attributes attribute tag2print TAGPRINTED attribute2print XAPPLIED_COLOR PROSTPROCESS USAGE
local TMP LOG LOGG
LIGHT=false
FORCE_PRINT=false
XAPPLY=false
MULTIPLE_ATTR=false
XAPPLIED_COLOR=g
TAGPRINTED=false
GETCONTENT=false
PROSTPROCESS=cat
Debug=${Debug:-false}
TMP=/tmp/xml_read.$RANDOM
USAGE="${C}${FUNCNAME}${c} [-cdlp] [-x command <-a attribute>] <file.xml> [tag | \"any\"] [attributes .. | \"content\"]
${nn[2]}  -c = NOCOLOR${END}
${nn[2]}  -d = Debug${END}
${nn[2]}  -l = LIGHT (no \"attribute=\" printed)${END}
${nn[2]}  -p = FORCE PRINT (when no attributes given)${END}
${nn[2]}  -x = apply a command on an attribute and print the result instead of the former value, in green color${END}
${nn[1]}  (no attribute given will load their values into your shell; use '-p' to print them as well)${END}"

! (($#)) && echo2 "$USAGE" && return 99
(( $# < 2 )) && ERROR nbaram 2 0 && return 99
# getopts:
while getopts :cdlpx:a: _OPT 2>/dev/null
do
{
  case ${_OPT} in
    c) PROSTPROCESS="${DECOLORIZE}" ;;
    d) local Debug=true ;;
    l) LIGHT=true; XAPPLIED_COLOR=END ;;
    p) FORCE_PRINT=true ;;
    x) XAPPLY=true; XCOMMAND="${OPTARG}" ;;
    a) XATTRIBUTE="${OPTARG}" ;;
    *) _NOARGS="${_NOARGS}${_NOARGS+, }-${OPTARG}" ;;
  esac
}
done
shift $((OPTIND - 1))
unset _OPT OPTARG OPTIND
[ "X${_NOARGS}" != "X" ] && ERROR param "${_NOARGS}" 0

fileXml=$1
tag=$2
(( $# > 2 )) && shift 2 && attributes=$*
(( $# > 1 )) && MULTIPLE_ATTR=true

[ -d "${fileXml}" -o ! -s "${fileXml}" ] && ERROR empty "${fileXml}" 0 && return 1
$XAPPLY && $MULTIPLE_ATTR && [ -z "${XATTRIBUTE}" ] && ERROR param "-x command " 0 && return 2
# nb attributes == 1 because $MULTIPLE_ATTR is false
[ "${attributes}" == "content" ] && GETCONTENT=true

while xml_read_dom; do
  # (( CR != 0 )) && break
  (( PIPESTATUS[1] != 0 )) && break

  if $ITSACOMMENT; then
    # oh wait it doesn't work on IBM AIX bash 3.2.16(1):
    # if [ "x${COMMENTS:(-2):2}x" == "x--x" ]; then COMMENTS="${COMMENTS:0:(-2)}" && ITSACOMMENT=false
    # elif [ "x${COMMENTS:(-3):3}x" == "x-->x" ]; then COMMENTS="${COMMENTS:0:(-3)}" && ITSACOMMENT=false
    if [ "x${COMMENTS:${#COMMENTS} - 2:2}x" == "x--x" ]; then COMMENTS="${COMMENTS:0:${#COMMENTS} - 2}" && ITSACOMMENT=false
    elif [ "x${COMMENTS:${#COMMENTS} - 3:3}x" == "x-->x" ]; then COMMENTS="${COMMENTS:0:${#COMMENTS} - 3}" && ITSACOMMENT=false
    fi
    $Debug && echo2 "${N}${COMMENTS}${END}"
  elif test "${TAG_NAME}"; then
    if [ "x${TAG_NAME}x" == "x${tag}x" -o "x${tag}x" == "xanyx" ]; then
      if $GETCONTENT; then
        CONTENT="$(trim "${CONTENT}")"
        test ${CONTENT} && echo "${CONTENT}"
      else
        # eval local $ATTRIBUTES => eval test "\"\$${attribute}\"" will be true for matching attributes
        eval local $ATTRIBUTES
        $Debug && (echo2 "${m}${TAG_NAME}: ${M}$ATTRIBUTES${END}"; test ${CONTENT} && echo2 "${m}CONTENT=${M}$CONTENT${END}")
        if test "${attributes}"; then
          if $MULTIPLE_ATTR; then
            # we don't print "tag: attr=x ..." for a tag passed as argument: it's usefull only for "any" tags so then we print the matching tags found
            ! $LIGHT && [ "x${tag}x" == "xanyx" ] && tag2print="${g6}${TAG_NAME}: "
            for attribute in ${attributes}; do
              ! $LIGHT && attribute2print="${g10}${attribute}${g6}=${g14}"
              if eval test "\"\$${attribute}\""; then
                test "${tag2print}" && ${print} "${tag2print}"
                TAGPRINTED=true; unset tag2print
                if [ "$XAPPLY" == "true" -a "${attribute}" == "${XATTRIBUTE}" ]; then
                  eval ${print} "%s%s\ " "\${attribute2print}" "\${${XAPPLIED_COLOR}}\"\$(\$XCOMMAND \$${attribute})\"\${END}" && eval unset ${attribute}
                else
                  eval ${print} "%s%s\ " "\${attribute2print}" "\"\$${attribute}\"" && eval unset ${attribute}
                fi
              fi
            done
            # this trick prints a CR only if attributes have been printed durint the loop:
            $TAGPRINTED && ${print} "\n" && TAGPRINTED=false
          else
            if eval test "\"\$${attributes}\""; then
              if $XAPPLY; then
                eval echo "\${g}\$(\$XCOMMAND \$${attributes})" && eval unset ${attributes}
              else
                eval echo "\$${attributes}" && eval unset ${attributes}
              fi
            fi
          fi
        else
          echo eval $ATTRIBUTES >>$TMP
        fi
      fi
    fi
  fi
  unset CR TAG_NAME ATTRIBUTES CONTENT COMMENTS
done < "${fileXml}" | ${PROSTPROCESS}
# http://mywiki.wooledge.org/BashFAQ/024
# INFO: I set variables in a "while loop" that's in a pipeline. Why do they disappear? workaround:
if [ -s "$TMP" ]; then
  $FORCE_PRINT && ! $LIGHT && cat $TMP
  # $FORCE_PRINT && $LIGHT && perl -pe 's/[[:space:]].*?=/ /g' $TMP
  $FORCE_PRINT && $LIGHT && sed -r 's/[^\"]*([\"][^\"]*[\"][,]?)[^\"]*/\1 /g' $TMP
  . $TMP
  rm -f $TMP
fi
unset ITSACOMMENT
}

এবং সর্বশেষে, rtrim, ট্রিম এবং ইকো 2 (স্টাডার থেকে) ফাংশন:

rtrim() {
local var=$@
var="${var%"${var##*[![:space:]]}"}"   # remove trailing whitespace characters
echo -n "$var"
}
trim() {
local var=$@
var="${var#"${var%%[![:space:]]*}"}"   # remove leading whitespace characters
var="${var%"${var##*[![:space:]]}"}"   # remove trailing whitespace characters
echo -n "$var"
}
echo2() { echo -e "$@" 1>&2; }

Colorization:

ওহ এবং আপনাকে প্রথমে সংজ্ঞায়িত করার জন্য কিছু ঝরঝরে রঙিন গতিশীল পরিবর্তনশীলগুলির প্রয়োজন হবে, এবং রফতানিও হবে:

set -a
TERM=xterm-256color
case ${UNAME} in
AIX|SunOS)
  M=$(${print} '\033[1;35m')
  m=$(${print} '\033[0;35m')
  END=$(${print} '\033[0m')
;;
*)
  m=$(tput setaf 5)
  M=$(tput setaf 13)
  # END=$(tput sgr0)          # issue on Linux: it can produces ^[(B instead of ^[[0m, more likely when using screenrc
  END=$(${print} '\033[0m')
;;
esac
# 24 shades of grey:
for i in $(seq 0 23); do eval g$i="$(${print} \"\\033\[38\;5\;$((232 + i))m\")" ; done
# another way of having an array of 5 shades of grey:
declare -a colorNums=(238 240 243 248 254)
for num in 0 1 2 3 4; do nn[$num]=$(${print} "\033[38;5;${colorNums[$num]}m"); NN[$num]=$(${print} "\033[48;5;${colorNums[$num]}m"); done
# piped decolorization:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'

কীভাবে সমস্ত জিনিস লোড করা যায়:

হয় আপনি কীভাবে ফাংশন তৈরি করবেন এবং এগুলি FPATH (ksh) বা FPATH (bash) এর একটি অনুকরণের মাধ্যমে লোড করবেন তা জানেন ither

যদি তা না হয় তবে কমান্ড লাইনে সমস্ত কিছু অনুলিপি করুন / আটকান।

এটা কিভাবে কাজ করে:

xml_read [-cdlp] [-x command <-a attribute>] <file.xml> [tag | "any"] [attributes .. | "content"]
  -c = NOCOLOR
  -d = Debug
  -l = LIGHT (no \"attribute=\" printed)
  -p = FORCE PRINT (when no attributes given)
  -x = apply a command on an attribute and print the result instead of the former value, in green color
  (no attribute given will load their values into your shell as $ATTRIBUTE=value; use '-p' to print them as well)

xml_read server.xml title content     # print content between <title></title>
xml_read server.xml Connector port    # print all port values from Connector tags
xml_read server.xml any port          # print all port values from any tags

ডিবাগ মোডের সাথে (-d) মন্তব্য এবং পার্সযুক্ত বৈশিষ্ট্যগুলি স্ট্যাডারে মুদ্রিত হয়


আমি উপরের দুটি ফাংশন নিম্নলিখিত উৎপন্ন ব্যবহার করার চেষ্টা করছি: ./read_xml.sh: line 22: (-1): substring expression < 0?
খামারবায়েস

লাইন 22:[ "x${ATTRIBUTES:(-1):1}x" == "x?x" ] ...
খামারবায়েস

দুঃখিত খামারবায়েস, এগুলি ব্যাশ শেল ফাংশন। আপনি যদি এগুলি শেল স্ক্রিপ্ট হিসাবে রূপান্তর করতে চান তবে অবশ্যই কিছুটা ছোটখাটো রূপান্তর আশা করতে হবে! এছাড়াও আপডেট করা ফাংশনগুলি আপনার ত্রুটিগুলি পরিচালনা করে;)
স্ক্যাভেন্জার

4

আমি কোনও খাঁটি শেল এক্সএমএল পার্সিং সরঞ্জাম সম্পর্কে অবগত নই। সুতরাং আপনার সম্ভবত অন্য একটি ভাষায় লেখা একটি সরঞ্জামের প্রয়োজন হবে।

আমার এক্সএমএল :: টুইগ পার্ল মডিউলটি এমন একটি সরঞ্জাম নিয়ে আসে: xml_grepযেখানে আপনি সম্ভবত যা চান তা লিখতে চান xml_grep -t '/html/head/title' xhtmlfile.xhtml > titleOfXHTMLPage.txt( -tবিকল্পটি আপনাকে xML এর পরিবর্তে পাঠ্য হিসাবে ফলাফল দেয়)


4

আর একটি কমান্ড লাইনের সরঞ্জাম হ'ল আমার নতুন জিডেল । এটি ইতিমধ্যে উল্লিখিত xpath / xMLstarlet এর বিপরীতে এক্সপথ 2 এবং এক্সকিউয়ারি সমর্থন করে।

শিরোনামটি এর মতো পড়তে পারে:

xidel xhtmlfile.xhtml -e /html/head/title > titleOfXHTMLPage.txt

এবং এটিতে ব্যাশকে একাধিক ভেরিয়েবল রফতানি করার জন্য দুর্দান্ত বৈশিষ্ট্য রয়েছে। উদাহরণ স্বরূপ

eval $(xidel xhtmlfile.xhtml -e 'title := //title, imgcount := count(//img)' --output-format bash )

$titleশিরোনাম এবং $imgcountফাইলের চিত্রের সংখ্যাতে সেট করে যা সরাসরি ব্যাশে পার্স করার মতো নমনীয় হওয়া উচিত।


এটাই আমার দরকার ছিল! :)
টমাস ডগার্ড

2

ঠিক আছে, আপনি এক্সপথ ইউটিলিটি ব্যবহার করতে পারেন। আমার ধারণা পার্লের এক্সএমএল :: এক্সপাথে এটি রয়েছে।


2

এক্সএমএল ফাইলগুলিতে লিনাক্স এবং উইন্ডোজ ফর্ম্যাটগুলির মধ্যে ফাইল পাথগুলির মধ্যে অনুবাদের জন্য কিছু গবেষণার পরে আমি আকর্ষণীয় টিউটোরিয়াল এবং এর সমাধান পেয়েছি:


2

যদিও বেশ কয়েকটি প্রস্তুত রেডিমেড কনসোল ইউটিলিটি রয়েছে যা আপনি যা করতে চান তা করতে পারে, সম্ভবত পাইথনের মতো সাধারণ উদ্দেশ্যমূলক প্রোগ্রামিং ল্যাঙ্গুয়েজে কয়েকটি লাইন কোড লিখতে কম সময় লাগবে যা আপনি সহজেই প্রসারিত এবং মানিয়ে নিতে পারেন আপনার চাহিদা.

এখানে একটি পাইথন স্ক্রিপ্ট যা lxmlপার্সিংয়ের জন্য ব্যবহার করে - এটি কোনও ফাইল বা ইউআরএলের নাম প্রথম প্যারামিটার হিসাবে নেয়, এক্সপ্যাথ এক্সপ্রেশনটিকে দ্বিতীয় প্যারামিটার হিসাবে নেয় এবং স্ট্রিং / নোডগুলি প্রদত্ত এক্সপ্রেশনটির সাথে মিলে যায়।

উদাহরণ 1

#!/usr/bin/env python
import sys
from lxml import etree

tree = etree.parse(sys.argv[1])
xpath_expression = sys.argv[2]

#  a hack allowing to access the
#  default namespace (if defined) via the 'p:' prefix    
#  E.g. given a default namespaces such as 'xmlns="http://maven.apache.org/POM/4.0.0"'
#  an XPath of '//p:module' will return all the 'module' nodes
ns = tree.getroot().nsmap
if ns.keys() and None in ns:
    ns['p'] = ns.pop(None)
#   end of hack    

for e in tree.xpath(xpath_expression, namespaces=ns):
    if isinstance(e, str):
        print(e)
    else:
        print(e.text and e.text.strip() or etree.tostring(e, pretty_print=True))

lxmlসঙ্গে ইনস্টল করা যাবে pip install lxml। উবুন্টুতে আপনি ব্যবহার করতে পারেন sudo apt install python-lxml

ব্যবহার

python xpath.py myfile.xml "//mynode"

lxml ইনপুট হিসাবে একটি URL গ্রহণ করে:

python xpath.py http://www.feedforall.com/sample.xml "//link"

দ্রষ্টব্য : যদি আপনার এক্সএমএলটির পূর্বনির্ধারিত কোনও পূর্বনির্ধারিত নেমস্পেস থাকে (উদাহরণস্বরূপ xmlns=http://abc...) তবে আপনাকে pনিজের অভিব্যক্তিগুলিতে প্রিফিক্সটি ('হ্যাক' দ্বারা সরবরাহিত) ব্যবহার //p:moduleকরতে হবে , উদাহরণস্বরূপ কোনও pom.xmlফাইল থেকে মডিউলগুলি পেতে । যদি pআপনার এক্সএমএলে ইতিমধ্যে উপসর্গটি ম্যাপ করা থাকে, তবে আপনাকে অন্য উপসর্গটি ব্যবহার করতে স্ক্রিপ্টটি পরিবর্তন করতে হবে।


উদাহরণ 2

একটি ওয়ান-অফ স্ক্রিপ্ট যা অ্যাপাচি মাভেন ফাইল থেকে মডিউল নামগুলি সরানোর সংকীর্ণ উদ্দেশ্যে কাজ করে। নোটের নাম ( module) কীভাবে ডিফল্ট নেমস্পেসের সাথে উপস্থাপিত হয় তা নোট করুন {http://maven.apache.org/POM/4.0.0}:

pom.xML :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modules>
        <module>cherries</module>
        <module>bananas</module>
        <module>pears</module>
    </modules>
</project>

মডিউল_সেক্সটেক্টর.পি :

from lxml import etree
for _, e in etree.iterparse(open("pom.xml"), tag="{http://maven.apache.org/POM/4.0.0}module"):
    print(e.text)

আপনি যখন অতিরিক্ত প্যাকেজ ইনস্টল করতে বা এড়িয়ে যেতে চান তবে এটি দুর্দান্ত। একটি বিল্ড মেশিনে, আমি একটি অতিরিক্ত pip installওভার apt-getবা yumকলকে ন্যায়সঙ্গত করতে পারি । ধন্যবাদ!
ই মোফাত

0

Yuzem এর পদ্ধতি ক্রম inversing দ্বারা উন্নত করা যায় <এবং >নিদর্শনাবলী rdomফাংশন এবং পরিবর্তনশীল বরাদ্দকরণ, যাতে করে:

rdom () { local IFS=\> ; read -d \< E C ;}

হয়ে:

rdom () { local IFS=\< ; read -d \> C E ;}

পার্সিংটি যদি এভাবে না করা হয় তবে এক্সএমএল ফাইলের সর্বশেষ ট্যাগটি কখনই পৌঁছায় না। whileলুপের শেষে আপনি যদি কোনও এক্সএমএল ফাইল আউটপুট করতে চান তবে এটি সমস্যাযুক্ত হতে পারে ।


0

আপনি এক্সএমএল বৈশিষ্ট্যগুলি চাইলে এটি কাজ করে:

$ cat alfa.xml
<video server="asdf.com" stream="H264_400.mp4" cdn="limelight"/>

$ sed 's.[^ ]*..;s./>..' alfa.xml > alfa.sh

$ . ./alfa.sh

$ echo "$stream"
H264_400.mp4

-1

যদিও এটি মনে হচ্ছে "কখনই XML, JSON ... কোনও উপযুক্ত সরঞ্জাম ছাড়া বাশ থেকে পার্স করবেন না" যথাযথ পরামর্শ, তবে আমি একমত নই। যদি এটি পাশের কাজ হয় তবে উপযুক্ত সরঞ্জামটি সন্ধান করা কোমরফুল হয়, তবে এটি শিখুন ... কয়েক মিনিটের মধ্যে এই কাজটি করতে পারে। আমার প্রোগ্রামগুলিতে উপরে উল্লিখিত সমস্ত এবং আরও ধরণের ডেটা নিয়ে কাজ করতে হবে। হেল, আমি যদি কয়েক মিনিটের মধ্যে সমস্যার সমাধান করতে পারি তবে আমার প্রয়োজন 5-7-10 বিভিন্ন ফর্ম্যাটগুলি পার্স করার জন্য 30 টি সরঞ্জাম পরীক্ষা করতে চাই না। আমি এক্সএমএল, জেএসওএন বা যা-ই হোক না কেন! তাদের সবার জন্য আমার একক সমাধান দরকার।

উদাহরণ হিসাবে: আমার স্মার্টহোম প্রোগ্রামটি আমাদের বাড়িগুলি চালায়। এটি করার সময়, এটি নিয়ন্ত্রণ করতে পারে না এমন অনেকগুলি বিভিন্ন ফর্ম্যাটে ডেটার আধিক্য পড়ে। আমি কখনই ডেডিকেটেড, সঠিক সরঞ্জাম ব্যবহার করি না যেহেতু আমি আমার প্রয়োজনীয় ডেটা পড়ার জন্য কয়েক মিনিটের বেশি সময় ব্যয় করতে চাই না। এফএস এবং আরএস সমন্বয়গুলির সাথে, এই অজানা সমাধানটি কোনও পাঠ্য বিন্যাসের জন্য পুরোপুরি কাজ করে। তবে, যখন আপনার প্রাথমিক কাজটি সেই বিন্যাসে ডেটা লোড দিয়ে প্রাথমিকভাবে কাজ করা হয় তখন এটি সঠিক উত্তর হতে পারে না!

গতকাল আমি বাশ থেকে এক্সএমএলকে পার্সিংয়ের সমস্যার মুখোমুখি হয়েছিল। যে কোনও শ্রেণিবদ্ধ ডেটা ফর্ম্যাটের জন্য আমি এটি কীভাবে এখানে করব। বোনাস হিসাবে - আমি ব্যাশ স্ক্রিপ্টের ভেরিয়েবলগুলিতে সরাসরি ডেটা নিযুক্ত করি।

পাতলা পড়া সহজতর করার জন্য, আমি পর্যায়গুলিতে সমাধান উপস্থাপন করব। ওপি পরীক্ষার ডেটা থেকে, আমি একটি ফাইল তৈরি করেছি: test.xML

পার্সিং 90 টি বর্ণে ডেটা বের করার এবং এক্সট্রাক্ট করার ক্ষেত্রে এক্সএমএল বলেছেন:

awk 'BEGIN { FS="<|>"; RS="\n" }; /host|username|password|dbname/ { print $2, $4 }' test.xml

আমি সাধারণত বেশি পঠনযোগ্য সংস্করণ ব্যবহার করি কারণ বাস্তব জীবনে পরিবর্তন করা সহজ কারণ আমার প্রায়শই আলাদাভাবে পরীক্ষা করা প্রয়োজন:

awk 'BEGIN { FS="<|>"; RS="\n" }; { if ($0 ~ /host|username|password|dbname/) print $2,$4}' test.xml

ফর্ম্যাটটি কীভাবে বলা হয় তা আমি চিন্তা করি না। আমি কেবল সহজ সমাধান চাই। এই বিশেষ ক্ষেত্রে, আমি ডেটা থেকে দেখতে পাচ্ছি যে নিউলাইনটি হ'ল রেকর্ড বিভাজক (আরএস) এবং <> সীমানা ক্ষেত্র (এফএস)। আমার আসল ক্ষেত্রে, আমি দুটি রেকর্ডের মধ্যে values ​​টি মানকে জটিল সূচীকরণ করেছি, সেগুলি সম্পর্কিত করে, ডেটা উপস্থিত থাকলে ক্ষেত্রগুলি (রেকর্ড) উপস্থিত থাকতে পারে বা নাও থাকতে পারে তা সন্ধান করে। সমস্যাটি নিখুঁতভাবে সমাধান করতে এটি 4 লাইন লাগিয়েছে। সুতরাং, এটি ব্যবহারের আগে প্রতিটি প্রয়োজনের সাথে ধারণাটি মানিয়ে নিন!

দ্বিতীয় অংশটি কেবল এটি দেখতে পাচ্ছে যে একটি লাইনে স্ট্রিং রয়েছে (আরএস) এবং যদি তা হয় তবে প্রয়োজনীয় ক্ষেত্রগুলি (এফএস) মুদ্রণ করে। উপরেরটি আমাকে এইভাবে ব্যবহৃত সর্বশেষ আদেশটি অনুলিপি করতে এবং অভিযোজিত করতে প্রায় 30 সেকেন্ড সময় নিয়েছে (4 গুণ বেশি দীর্ঘ)। আর এটাই! 90 টি চর হয়েছে

তবে, আমার স্ক্রিপ্টে আমার সবসময় ঝরঝরে ডেটা ঝরঝরে করে নেওয়া দরকার। আমি প্রথমে এরকম নির্মাণগুলি পরীক্ষা করে দেখি:

awk 'BEGIN { FS="<|>"; RS="\n" }; { if ($0 ~ /host|username|password|dbname/) print $2"=\""$4"\"" }' test.xml

কিছু ক্ষেত্রে আমি প্রিন্টের পরিবর্তে প্রিন্টফ ব্যবহার করি। আমি যখন সবকিছু দেখতে ভাল দেখি তখন আমি কেবল ভেরিয়েবলগুলিকে মান নির্ধারণ শেষ করি। আমি জানি অনেকেই মনে করেন "ইভাল" "দুষ্ট", মন্তব্য করার দরকার নেই :) ট্রিক বছরের পর বছর ধরে আমার চারটি নেটওয়ার্কে পুরোপুরি কাজ করে। তবে শিখতে থাকুন কেন বুঝতে পারছেন না কেন এটি খারাপ অভ্যাস হতে পারে! ব্যাশ ভেরিয়েবল অ্যাসাইনমেন্ট এবং পর্যাপ্ত ব্যবধান সহ, আমার সমাধানটিতে সবকিছু করতে 120 টি অক্ষর প্রয়োজন needs

eval $( awk 'BEGIN { FS="<|>"; RS="\n" }; { if ($0 ~ /host|username|password|dbname/) print $2"=\""$4"\"" }' test.xml ); echo "host: $host, username: $username, password: $password dbname: $dbname"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.