48

変数としてスクリプトに読み込まれた xml ドキュメントから値を抽出しようとしています。元の変数$dataは次のとおりです。

<item> 
  <title>15:54:57 - George:</title>
  <description>Diane DeConn? You saw Diane DeConn!</description> 
</item> 
<item> 
  <title>15:55:17 - Jerry:</title> 
  <description>Something huh?</description>
</item> 

最初のタイトル値を抽出したいので、

15:54:57 - George:

私はsedコマンドを使用しています:

title=$(sed -n -e 's/.*<title>\(.*\)<\/title>.*/\1/p' <<< $data)

ただし、これは2番目のタイトル値のみを出力します:

15:55:17 - Jerry:

私が間違ったことを誰か知っていますか?ありがとう!

4

3 に答える 3

92

Charles Duffeyが述べているように、XML パーサーは適切な XML 解析ツールで解析するのが最適です。1回限りのジョブの場合、次のように動作するはずです。

grep -oPm1 "(?<=<title>)[^<]+"

テスト:

$ echo "$data"
<item> 
  <title>15:54:57 - George:</title>
  <description>Diane DeConn? You saw Diane DeConn!</description> 
</item> 
<item> 
  <title>15:55:17 - Jerry:</title> 
  <description>Something huh?</description>
$ title=$(grep -oPm1 "(?<=<title>)[^<]+" <<< "$data")
$ echo "$title"
15:54:57 - George:
于 2013-06-27T02:56:46.270 に答える
32

XMLStarlet または別の XPath エンジンが、このジョブに適したツールです。

たとえばdata.xml、以下を含む場合:

<root>
  <item> 
    <title>15:54:57 - George:</title>
    <description>Diane DeConn? You saw Diane DeConn!</description> 
  </item> 
  <item> 
    <title>15:55:17 - Jerry:</title> 
    <description>Something huh?</description>
  </item>
</root>

...次のようにして、最初のタイトルのみを抽出できます。

xmlstarlet sel -t -m '//title[1]' -v . -n <data.xml

この作業に sed を使おうとすると面倒です。たとえば、タイトルに属性がある場合、正規表現ベースのアプローチは機能しません。CDATA セクションを処理しません。名前空間のマッピングを正しく認識しません。文書化された XML の一部がコメント アウトされているかどうかを判断できません。Brewster &amp; Jobs属性参照 (への変更など) のエスケープを解除しませんBrewster & Jobs

于 2013-06-27T03:12:31.000 に答える
12

私は、適切な XML パーサーが正しい道であるという Charles Duffy の意見に同意します。

しかし、あなたのsedコマンドのどこが悪いのですか(または意図的にそれをしましたか?)。

  • $data引用されていないため$data、シェルの単語分割、ファイル名の展開などの影響を受けます。結果の 1 つは、XML スニペットのスペースが保持されないことです。

したがって、特定の XML 構造が与えられた場合、この変更されたsedコマンドは機能するはずです

title=$(sed -ne '/title/{s/.*<title>\(.*\)<\/title>.*/\1/p;q;}' <<< "$data")

基本的に を含む行についてはtitle、タグ間のテキストを抽出してから終了します (2 番目の を抽出しないようにします<title>) 。

于 2013-06-27T03:28:28.830 に答える