sedを使用してXMLファイルから特定のテキストを取得する

sedを使用してXMLファイルから特定のテキストを取得する

なぜ私はこれを得ることができないのか分かりません。何時間もコマンドを検索してテストしましたが、何も見つかりませんでした。

テキストは次のとおりです

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><result expand="changes,testResults,metadata,logEntries,plan,vcsRevisions,artifacts,comments,labels,jiraIssues" key="EP-ED-JOB1-174" state="Failed" lifeCycleState="Finished" number="174" ....

そして私はその部分を引き出したいと思います。state="Failed" おそらく…state="Successful"

私は百万のバリエーションを試しました。

sed '/state=".*"/p' htmlResponse.txt

しかし、角かっこ、エスケープスラッシュなどはフルテキストブロックと一致するようです。私の正規表現にはどんな問題がありますか?

答え1

「正規表現がXMLを解析するのに十分ではないため、適切なXMLパーサーを使用する必要があります」という必須の説明を取り上げて、行にはsed2つの問題があります。

  1. ".*"".一致するので、最初から最後まで一致します。"
  2. このsedコマンドは/.../p印刷します全体的に正規表現と一致する場合。

迅速で汚いHTMLスクレイピングシェルスクリプトのために、次の2つのことをお勧めします。

  1. "[^"]*"「引用符、引用符以外の文字、閉じる引用符」と一致します。
  2. grep -o正規表現に一致するファイルの部分を抽出する方がはるかに簡単です。

したがって、これはコマンドを次のようにします。

grep -o 'state="[^"]*"'

または本当に〜しなければならないsedを使用してください:

sed -n 's/.*\(state="[^"]*"\).*/\1/p'

答え2

正しい方法は、次のXMLパーサーを使用することです。xmlstarlet:

printf 'state="%s"\n' $(xmlstarlet sel -t -v "//result/@state" -n htmlResponse.txt)

出力:

state="Failed"

属性値のみを取得します(ノードがresult複数ある場合はすべてのノードで)。

xmlstarlet sel -t -v "//result/@state" -n htmlResponse.txt

答え3

行全体を一致させて印刷することもできます。ただ一致するグループ:

sed -r 's/.*state="([^"]*)".*/\1/' htmlResponse.txt

Failedこれは実際にあなたが望むものと思われるor Successfulstate=前の部分を除く)を取り出すことです。ただし、必要に応じて簡単に再追加するか、少し異なる正規表現を使用できます。ウッズが答えたように

しかし、次のように山ディップが言及される、これは正規表現を使用してHTML(またはXML)を解析することは単に信頼できません。。コンテンツをインタラクティブに消費grepまたはsed検索することも重要ですが、これが重要なタスクを実行する必要があるスクリプトの一部である場合そして実際に働く、XMLを正しく解析する必要があります。

関連情報