次の便利な find コマンドは、名前タグの値を出力します。
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \;
問題は、/ tmpの下に複数のxmlファイルがある場合、どのxmlファイルに名前タグがあるのかわからないことです。
つまり、この find 構文は Name 値を出力します。
しかし、xmlファイル名はありません。
grepが一致したときにファイル名を印刷する方法を提案してください。
(?<=<Name>).*(?=</Name>)
答え1
適切なXMLパーサー(ここで使用するもの)を使用してファイル名の接尾辞がat以下のすべてのXMLファイルからすべてのノードのxmlstarlet
値を抽出するには、次のようにします。Name
.xml
/tmp
find /tmp -type f -name '*.xml' -exec xmlstarlet sel -t -v '//Name' -nl {} +
これは実際にいいえ<Name>
開いたタグと対応する閉じるタグは同じ行に</Name>
なけれName
ばなりませんgrep
。
xmlstarlet
現在処理中のファイル名などの追加情報出力を使用し、ファイルに実際にノードがある場合にのみこれを実行するには、上記のコマンドのName
呼び出しxmlstarlet
を次のように置き換えます。find
xmlstarlet sel -t -i '//Name' -o '### ' -f -o ':' -nl -v '//Name' -nl
これにより、ファイルにノードが含まれている場合にのみ、プレフィックス###
とサフィックスが付いたXMLファイルのパス名が出力されます。その後、文書の各ノード値が続きます。:
Name
Name
使用grep
:
grep
コマンドラインに複数のファイルが指定されている場合は、一致を含むファイルのファイル名が常に出力されます。ファイルが1つだけ渡されると、ファイル名は印刷されません。
実際の一致と一緒にファイル名を常に印刷するには、/dev/null
次のファイルをgrepに追加ファイルとして追加します。
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} /dev/null \;
または、通話数を潜在的に減らすには、次の方法をgrep
使用しますfind -exec grep ... {} +
。
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' /dev/null {} +
少なくとも、GNU、OpenBSD、およびFreeBSDは、ファイルが1つだけ提供されていても常にファイル名を印刷するフラグをサポートしgrep
ます。あなたがそれを使用しているので、おそらくGNUを使用しているでしょう。grep
-H
grep -P
grep
答え2
grep に "-H" パラメーターのみを指定すると、grep が処理するファイルが 1 つしかない場合でも (あなたの場合のように) ファイル名は常に印刷されます。
答え3
これはgrep
xml / htmlファイル(文書)を解析するのに適したツールではなく、強力で信頼性の高いソリューションを提供しません。 「正しい」xml / htmlパーサーを使用してください。xmlstarlet
:
find /tmp -type f -name '*.xml' -exec xmlstarlet sel -t -m "//Name" -f -n {} \;
xmlstarlet sel -t -m "//Name" -f -n
-f
-入力ファイル名は、入力xml文書が()XPATH式と一致する場合にのみ印刷されます-m
(オプションで確認)。"//Name"
答え4
見つかった行の後にファイル名を印刷しても問題ない場合は、いつでも「-print」オプションを見つけることができます。
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \; -print