我想按内容在源树中递归查找文件。我使用 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 个字符串的那些行上。