2012-07-10 40 views
3

我正在使用grep命令从文件中获取所需的信息。我正在使用两个像下面这样的grep语句:grepping multiple strings

XXXX='grep XXXX FILE A|sort|uniq|wc -l' 
grep YYYY FILE A|uniq| > FILE B 

现在文件被遍历两次。但我只想知道,如果我能够在单个文件遍历中执行这两个步骤,即我想知道是否可以使用类似于egrep的地方,在这里我可以grep两个字符串和一个字符串,我将使用它在另一个字符串中存储一个变量并输出到一个文件中。

回答

1

您可以使用下面的代码。这里我们只搜索一次包含所有文件中的XXXX或YYYY的行,并将结果行存储到一个数组中。然后我们使用这个数组的元素来选择包含XXXX的行和包含YYYY的行。

filtered=`grep -E '(XXXX|YYYY)' FILE A` 
XXXX=`for line in ${filtered[@]}; do echo $line; done | grep XXXX | sort | uniq | wc -l` 
for line in ${filtered[@]}; do echo $line; done | grep YYYY | uniq > FILE B 

所以文件不会遍历两遍!

+0

如果输入尺寸大于可用内存,并且仅对小批量数据有意义,则此方法将很快爆炸。 – mavam 2012-07-10 23:18:32

+0

如果目的是将数据存储在变量中(在这个问题中就是这种情况),大量的输入总是会填满内存。 – mostar 2012-07-11 16:45:03

0

或使用egrep的一个脱节:

egrep '(XXXX|YYYY)' FILE A | sort | uniq | ... 

或者AWK:

awk '/XXXX|YYYY/' FILE A | sort | uniq | ... 
+0

谢谢你的回答..我理解你的观点......但是我怎样才能把2个grep语句的结果存储在两个变量 – User 2012-07-10 22:06:02

+0

你的输入数据有多大?这只对小数据量有意义。看看awk中的关联数组。 – mavam 2012-07-10 23:17:11

+0

输入数据在200 MB的范围内..其大文件 – User 2012-07-11 04:09:59

0

有一个尾随的'|'在你的问题的象征,也许你想要的YYYY线也通过管道输送到sort,在这种情况下,你可以简单地做(或使用sort -u!):

awk '/XXXX/ { if(!x[$0]++) xcount += 1 } 
    /YYYY/ { if(!y[$0]++) ycount += 1 } 
    END { print "XXXX:", xcount 
     print "YYYY:", ycount 
     for(i in y) print i | "sort > FILEB" 
    }' FILE 

此扫描文件一次,递增计数器,每当看到包含适当模式的uniq线。请注意,在YYYY行数组上迭代的顺序在这里没有很好的定义,所以排序是必须的。某些版本的awk提供了对数组进行排序而不依赖外部实用程序的功能,但并非全部都是这样。使用Perl,如果你想这样做。