私はスクリプトに変数として読み込まれた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:
誰かが私が間違ったことを知っていますか?ありがとう!
Charles Duffey が述べているように、XMLパーサーは適切なXML解析ツールで最適に解析されます。一度だけの仕事では、次のように動作するはずです。
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:
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 & Jobs
からBrewster & Jobs
)など。
私は、適切なXMLパーサーが正しい方法であるというCharles Duffyに同意します。
しかし、あなたのsed
コマンドの何が問題なのか(または意図的にそれをしましたか?)。
$data
は引用されなかったので、$data
は、シェルのWord分割、ファイル名の展開などの影響を受けます。結果の1つは、XMLスニペットの間隔が保持されないことです。したがって、特定のXML構造を考えると、この変更されたsed
コマンドは機能するはずです。
title=$(sed -ne '/title/{s/.*<title>\(.*\)<\/title>.*/\1/p;q;}' <<< "$data")
基本的に、title
を含む行については、タグ間のテキストを抽出し、終了します(したがって、2番目の<title>
)