使用 xargs 来 grep 多个模式

use*_*394 13 grep xargs

我有一个文件,其中包含我想要 grep 的术语,每个术语都是文件中的一行。我在想我可以用 xargs 做到这一点。我可以从这样的手册页中的示例中收集到什么

find ./work -print0 | xargs -0 rm
Run Code Online (Sandbox Code Playgroud)

是 xargs 将预管道命令的输出附加到其参数的末尾。因此,如果 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
Run Code Online (Sandbox Code Playgroud)

xargs 是正确的工具吗?如果是这样,语法是什么?

Kev*_*vin 18

是的,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.)
Run Code Online (Sandbox Code Playgroud)

因此,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
Run Code Online (Sandbox Code Playgroud)

-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.)
Run Code Online (Sandbox Code Playgroud)