bash / bin / grep:参数列表太长(使用--file选项)

时间:2016-01-25 09:40:45

标签: bash grep

我有一个包含33.869行的文本文件,我必须过滤30.067行。

举个例子:

文件: input.txt (csv与33.869行一样)

#00001:A123456.10.101.102,first,row,value2,1
#00002:A123456.10.101.103,second,row,value7,85
(omissis)
#33869:A123456.25.170.180,last,test,value9,0

文件: filter.txt (由“\ n”以30.067行分隔的值列表)

A123456.10.101.102
A123456.10.101.103
(omissis)
A123456.24.150.115

(预期)输出文件: output.txt (csv喜欢从input.txt获取30.067行):

#00001:A123456.10.101.102,first,row,value2,1
#00002:A123456.10.101.103,second,row,value7,85
(omissis)
#30067:A123456.24.150.115,whatever,x,y,99

我正在使用的命令是:

#!/bin/bash
/bin/grep --file="filter.txt" input.txt > output.txt

但返回的错误是

/bin/grep: Argument list too long

我是否被迫在较小的块中拆分“filter.txt”?

允许的限制是什么?

我没有找到man code命令的限制。

4 个答案:

答案 0 :(得分:3)

如果输入文件中没有正则表达式,则应切换到可以读取大量输入记录的grep -F

如果不这样做,拆分输入文件比在同一个文件上运行30,000多次grep次迭代效率要高得多。

这里分成10,000行的块;适应不同的因素应该是微不足道的。

#!/bin/sh

t=$(mktemp -d -t fgrepsplit.XXXXXXXXXXXX) || exit
trap 'rm -rf "$t"' EXIT       # Remove temp dir when done
trap 'exit 127' HUP INT TERM  # Remove temp dir if interrupted, too

split -l 10000 "$1" "$t"/pat

for p in "$t"/pat*; do
    grep -F -f "$p" "$2"
done

答案 1 :(得分:2)

根据你所写的内容,我想知道grep是否适合这项工作。使用grep,您通常会尝试应用一小组匹配规则,表示为正则表达式。在您的情况下,您匹配一长串文字。

这似乎是找到full_file.txtfiltered.txt共有的行的情况。您可能希望查看以下工具来实现此目的:

  • joinhttp://linux.die.net/man/1/join)为您提供两个文件共有的行。请注意,必须对这两个文件进行排序。您可以使用流程替换来实现此目的。
  • combinehttp://linux.die.net/man/1/combine)是一个更通用的实用程序,不需要对输入进行排序。但它可能无处不在。

答案 2 :(得分:1)

如何在文件的每一行上进行迭代?类似的东西:

while IFS= read -r  i ; do
   grep "$i" full_file.txt
done < grep_filter.txt >filtered.txt

答案 3 :(得分:1)

使用awk

awk -F"[:,]" 'FNR==NR{a[$2]=$0;next} ($0 in a) {print a[$0]}'  input.txt filter.txt