
我想按內容在來源樹中遞歸查找文件。我使用 grep 嘗試了以下操作:
$ grep -rn printf | grep %s | grep bcm_errmsg\(rv\)
這會按我想要的方式返回每一行,但現在,我想獲取每個匹配文件的文件名,所以我將其更改為:
$ grep -rn printf | grep %s | grep -l bcm_errmsg\(rv\)
但我沒有列印檔名,而是只得到
(standard input)
列印到標準輸出。如何修復此問題以獲取每個文件名和路徑(以sed
在其上使用)?
我想要做的:尋找每個printf
包含以下行的文件%s
,bcm_errmsg(rv)
然後將以下 sed 命令應用於找到的文件:
sed -i 's/%s/%d/g; s/bcm_errmsg(rv)/rv/g;'
答案1
我認為你把事情過於複雜化了。要foo
在目前目錄和子目錄中的所有檔案中尋找字串,只需執行
grep -r "foo" *
預設情況下,grep 輸出匹配行,前面加上找到它的檔名。
以下將僅輸出檔名,而不輸出匹配行:
grep -rl "foo" *
答案2
按照@steeldriver的最初想法,你可以這樣做:
egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/'
答案3
grep -rlZP '(?=.*printf)(?=.*%s)(?=.*bcm_errstr\(rv\))' . |
xargs -r0 sed -i -e '
/%s/!b
/printf/!b
/bcm_errstr(rv)/!b
s/%s/%d/g;s/bcm_errstr(rv)/rv/g
'
我們首先運行一個遞歸目錄。從目前目錄掃描具有以下字串的檔案: printf、%s 和 bcm_errstr(rv) 位於同一行,但可能以任意順序。grep
幫助我們做到這一點的選項是:
-r
=> 將遞歸啟動目前目錄及以下目錄中的所有檔案。-l
=> 將列出符合條件的檔案名,即所有 3 個字串位於同一行。-Z
=> 所選檔案名稱以空分隔(\0)而不是通常的換行符號(\n),以便我們能夠處理任何類型的檔案名稱。-P
=> 啟用 Perl 正規表示式引擎,從而我們能夠使用前瞻來確定 3 個字串是否存在於同一行中。
在管道的另一端,xargs
正在等待接收檔案名,以 \0 分隔。然後,它盡可能地將所有這些檔案名稱提供給 sed 命令行。您已經從上一個問題中知道了 sed 命令,它在其中執行 subs。僅在同一行包含 3 個字串的那些行上。