特定のタグ名を含むxmlファイルを見つけて、タグ名間の単語を印刷します。

特定のタグ名を含むxmlファイルを見つけて、タグ名間の単語を印刷します。

次のようにxmlファイル形式を見つけることができます。

find /tmp/ -type f -name '*.xml'

しかし、次のようなXMLのみを見つけるように構文をどのように変更できますか?

<Name>some words</Name>

次の間に内容を印刷します。

<Name> ------ </Name>

期待される出力

some words      

例 – xml ファイルには次のものが含まれます。

<Name>files_with_extra_data</Name>

期待される出力

files_with_extra_data

答え1

簡単な解決策はsedを使用することです。

find /tmp -name '*.xml' -exec sed -n 's/<Name>\([^<]*\)<\/Name>/\1/p' {} +

正規表現はタグを一致させ、タグ間の内容を印刷します。エスケープ文字を削除すると、読みやすくなります。

s / <Name>([^<]*)</Name> / \1 

角かっこは "<"以外のすべての文字と一致し、\ 1にマップされます。

コメントで述べたように、これは簡単な解決策になります。正規表現は、構造化テキストのすべての可能な変形に対処することはできません。したがって、タグまたは他のタグの間に複数行がある場合は機能せず、実際のXMLパーサーを使用する必要があります。

答え2

このような単純なXML操作の場合は、次を使用します。XML2そしてcut。 (またはsed、またはawk、またはperl)。

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | grep '/Name=' |
  cut -d '=' -f2-

または

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | sed -n -e 's/^[^=]*\/Name=//p'

または

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | 
  awk -F'=' '/Name=/ {$1=""; sub(/^ /,"",$0); print }'

sub()awkバージョンの関数呼び出しは、$ 1を ""に設定した後に残った先行スペースを削除します。awkは入力行からフィールドを削除できませんsplit()。 . 不要なフィールドを削除し、配列を印刷用の文字列に連結しますawkjoin()perl

または

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; |
  perl -F= -lane 'if (m:/Name=:) { delete @F[0]; print @F}'

xml2XML形式のデータを、行ベースのテキストユーティリティ(たとえば、、、、awkなどsed)を使用して処理するのに適した行ベースのperl形式に変換します。2xmlラインベースの形式を正しい形式のXMLに変換するプログラムが付属しています。

より複雑なタスクに使用します。xmlstarlet

xmlstarletXMLファイルのデータを一覧表示、照会、抽出、および変更するために使用できるXML処理ツール。

どちらもDebianや他のLinuxディストリビューション用にパッケージ化できます。


私の考えのための最善の解決策は、類似またはperlXMLpython解析ライブラリを持つ言語を使用することです。 xmlstarletシェルでXMLファイルを処理するのに適していますが、非常に複雑な検索のためのコマンドラインを書くことは、スクリプトを書いたりperl作業を実行したりするよりもpython多くの作業になります(読み取りとデバッグが難しくなります)。部分的には、私はこれらの言語でより多くのプログラミングをしており、使いやすくなることがわかったからです...だからです。非常に特定の日にのみ使用できるドメイン固有の言語/ツールではない操作。

答え3

そしてpcregrep

pcregrep -rMh --include='\.xml\z' -o1 '(?s)<name>(.*?)</name>' .

答え4

sed -n '/Name/{s/.*<Name>//;s/<\/Name.*//;p;}' "$FULL_XML_PATH"

関連情報