如何在腳本中安全地使用 grep 的輸出?

如何在腳本中安全地使用 grep 的輸出?

在腳本中,我想尋找包含一些文字的檔案。我grep需要知道在其中找到文字的文件,以及在其中找到文字的文件中的整行:。是否有某種我可以使用的--porcelain模式grep,就像git指令經常使用的模式?

範例:我有一個資料夾,裡面裝滿了test-num:1:date:jan-2我想要 grep 的檔案。這些文件包含FAILURE:<some reason>or SUCCESS:<some reason>(以及其他內容)。我需要一個腳本來搜尋某些原因並儲存檔案名稱和原因(整行文字都可以)以供以後處理。輸出可以是任何類型的資料結構,只要我可以對其運行程式碼即可。

答案1

不存在諸如 之類的東西grep --porcelain,在 UNIX 中,處理檔案名稱中的特殊字元始終是事後才想到的。您可以嘗試這樣的事情,但要以效率為代價:

pattern='some pattern'
for file in ./*; do
    grep -- "$pattern" "$file" | while read -r line; do
        printf 'file: %s, line: %s\n' "$file" "$line"
    done
done

答案2

最近(-ish)版本的 GNU grep 有一個選項-Z可以使輸出明確,但它主要針對像grep -lZ … | xargs -0.如果您列出行內容,空字節替換冒號並且行內容仍然以換行符號結束,它仍然有效,但是 shell 不擅長處理空字節,因此您將很難解析此輸出。

一個簡單的解決方案(效能略有下降)是對每個檔案單獨執行 grep。

另一個解決方案是使用 Perl 或 Python 等語言。 Perl 非常擅長模擬 grep; grep REGEX基本上是perl -ne '/REGEXP/ and print'

但如果輸出實際上並不含糊,您可能根本不需要這個。例如,如果匹配行不包含冒號,則檔案名稱是一行中直到最後一個冒號的所有內容。如果匹配的行全部以SUCCESSor開頭,FAILURE並且這些單字沒有出現在檔案名稱中,那麼您可以使用它來定位分隔符號等。

1除非用於-z過濾以 null 結尾的記錄而不是以換行符結尾的記錄,否則 null 既是文件名終止符又是結果終止符;沒有-o輸出仍然是明確的,交替輸出記錄是檔案名稱和輸出中的匹配記錄。

答案3

如何安全地使用 grep 的輸出在腳本中?

...輸出可以是任何類型資料結構,只要我可以在上面運行程式碼即可。

Shell 腳本實際上沒有資料結構。有數組,但僅此而已 - 將管道輸出安全地輸入數組並不容易。 (檔名包含換行符。

最好的方法是運行程式碼在 shell 腳本中對檔案進行操作的方法是僅對檔案執行程式碼,而不是嘗試儲存檔案名稱以供以後使用。

為此,請使用find

find somedir -type f -exec grep -q somepattern {} \; -exec somecommand {} \;

然而,透過更仔細地閱讀你的問題,看起來你實際上並不想運行程式碼在您的文件中,您只想對某些行進行一些文字處理。在這種情況下,GNU Grep 選項-z可能就是您想要的。再加上 Sed 或 Awk 的知識,就可以解決您的問題。


更改文件命名約定可能是明智之舉。

相關內容