我有一个文件,其中包含我想要 grep 的术语,每个术语都是文件中的一行。我想我可以用 xargs 来做到这一点。我可以从这样的手册页的示例中收集到什么
find ./work -print0 | xargs -0 rm
是 xargs 将 pre-pipe 命令的输出附加到其参数的末尾。因此,如果 find 返回report.doc
,则 xargs 将构造rm report.doc
。这种理解正确吗?
因此,由于我希望文件中的值位于 grep 命令的中间,因此我需要指定一个占位符。在玩的过程中,我尝试过{}
,但没有成功:
$> cat strings.txt | xargs grep {} subdirectory/*
grep: string1: No such file or directory
grep: string2: No such file or directory
xargs 是正确的工具吗?如果是这样,语法是什么?
答案1
是的,find ./work -print0 | xargs -0 rm
将执行类似的事情rm ./work/a "work/b c" ...
。您可以使用 进行检查echo
,find ./work -print0 | xargs -0 echo rm
将打印将要执行的命令(除了空格将被适当转义,尽管echo
不会显示这一点)。
要将xargs
名称放在中间,您需要添加-I[string]
,其中[string]
是您想要用参数替换的内容,在本例中您将使用-I{}
,例如<strings.txt xargs -I{} grep {} directory/*
。
你真正想要使用的是grep -F -f strings.txt
:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file
contains zero patterns, and therefore matches nothing. (-f is
specified by POSIX.)
因此,grep -Ff strings.txt subdirectory/*
将找到所有出现的任何字符串strings.txt
作为文字,如果您删除该-F
选项,则可以在文件中使用正则表达式。其实你grep -F "$(<strings.txt)" directory/*
也可以用。如果你想练习find
,可以使用总结中的最后两个例子。如果您想进行递归搜索而不仅仅是第一级搜索,那么您有几个选项,也在摘要中。
概括:
# grep for each string individually.
<strings.txt xargs -I{} grep {} directory/*
# grep once for everything
grep -Ff strings.txt subdirectory/*
grep -F "$(<strings.txt)" directory/*
# Same, using file
find subdirectory -maxdepth 1 -type f -exec grep -Ff strings.txt {} +
find subdirectory -maxdepth 1 -type f -print0 | xargs -0 grep -Ff strings.txt
# Recursively
grep -rFf strings.txt subdirectory
find subdirectory -type f -exec grep -Ff strings.txt {} +
find subdirectory -type f -print0 | xargs -0 grep -Ff strings.txt
-l
如果您不需要查看实际行,您可能希望使用该选项来仅获取每个匹配文件的名称:
-l, --files-with-matches
Suppress normal output; instead print the name of each input
file from which output would normally have been printed. The
scanning will stop on the first match. (-l is specified by
POSIX.)
答案2
xargs
fgrep
如果您的要匹配的字符串文件仅包含字符串,而不包含正则表达式,则可能不是我建议的最佳工具。
fgrep -f strings.txt subdirectory/*
我建议fgrep
使用传统的 Unix grep
,并且egrep
没有“-f”选项。我相信 GNUgrep
确实egrep
有“-f”选项,所以如果你的文件中有正则表达式,你会想要使用 GNU 版本。