Linux
find + grep 匹配時如何列印文件名
以下有用的查找命令,列印名稱標籤中的值
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \;
問題是如果我們在 /tmp 下有幾個 xml 文件,那麼我們永遠不知道哪個 xml 文件有 Name 標籤
或者換句話說,這個 find 語法將列印 Name 的值
但沒有 xml 文件名
請建議如何在 grep 匹配時列印文件名:
(?<=<Name>).*(?=</Name>)
要使用適當的 XML 解析器(這裡我使用
xmlstarlet
)來提取Name
所有 XML 文件中的所有節點的值,這些文件.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
如果在命令行上給出了多個文件,將始終輸出包含匹配項的文件的文件名。如果只傳遞一個文件,則不會列印文件名。要強制始終將文件名與實際匹配一起列印,請將
/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
grep
以及grep
OpenBSD 和 FreeBSD 上也支持-H
始終列印文件名的標誌,即使只給出一個文件。既然您使用了 ,那麼您可能無論如何grep -P
都在使用 GNU 。grep