3

我试图通过 xargs 传递 grep 查询,同时通过进程替换传递文件。

command1 | xargs -I{} grep {} <(command2)

制作虚拟文件

for f in {1..50}; do echo $f >> test50.txt; done

for f in {25..30}; do echo $f >> test5.txt; done

xargs 和 grep 的进程替换

cat test5.txt | xargs -I{} grep {} <(cat test50.txt)

输出是:

25

所需的输出是:

25
26
27
28
29
30

我认为问题在于 grep 如何接收输入文件,它在一行之后停止,而我希望它搜索整个输入文件

4

3 回答 3

3

考虑这个

cat test5.txt | xargs -I{} echo {} <(cat test50.txt)

产生

25 /dev/fd/63
26 /dev/fd/63
27 /dev/fd/63
28 /dev/fd/63
29 /dev/fd/63
30 /dev/fd/63

因此这

cat test5.txt | xargs -I{} cat {} <(cat test50.txt)

输出

cat: 25: No such file or directory
1
2
--cutted for brevity--
49
50
cat: 26: No such file or directory
cat: 27: No such file or directory
cat: 28: No such file or directory
cat: 29: No such file or directory
cat: 30: No such file or directory

您的问题不在于 bash grep,而process substitution在于 bash。进程替换创建一个命名管道。接下来,来自该管道的所有数据都在第一次调用提供给的命令时使用xargs(在您的示例中,它是grep,在我的上面echo和中cat),因此第一个25参数是带有的。

这将起作用

cat test5.txt | xargs -I{} bash -c " grep {} <(cat test50.txt)"

process substitution因为它为每次grep调用独立创建“新鲜” 。

于 2018-02-19T20:26:58.360 回答
2

使用 GNU Parallel,它看起来像这样:

cat test5.txt | parallel 'grep {} <(cat test50.txt)'
于 2018-03-05T10:02:54.540 回答
2

不需要xargs因为grep已经有一种方法可以从文件中指定搜索词

$ seq 50 > f1
$ seq 25 30 > f2
$ grep -Fxf f2 f1
25
26
27
28
29
30

man grep

-F, --fixed-strings 将 PATTERN 解释为固定字符串的列表(而不是正则表达式),由换行符分隔,其中任何一个都将被匹配。

-x, --line-regexp 仅选择与整行完全匹配的匹配项。对于正则表达式模式,这就像给模式加上括号,然后用 ^ 和 $ 包围它。

-f FILE, --file=FILE 从 FILE 中获取模式,每行一个。如果此选项被多次使用或与 -e (--regexp) 选项结合使用,则搜索所有给定的模式。空文件包含零个模式,因此不匹配任何内容。

于 2018-02-20T03:48:53.307 回答