多个字符串的grep

3

我正在使用grep命令从一个文件中获取所需的信息。我使用了两个grep语句,类似于下面的语句:

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

现在这个文件被遍历了两次。但我只想知道,是否能够在一次文件遍历中完成这两个步骤。也就是说,我想知道是否可以使用类似于egrep的东西,我可以用它来grep两个字符串,并且其中一个字符串我将用来存储到一个变量中,另一个字符串的输出则写入到一个文件中。

3个回答

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

因此,文件不会被遍历两次!


如果输入大小超过可用内存,此方法将很快崩溃,并且仅适用于小数据批处理。 - mavam
如果目的是将数据存储在变量中(这是本问题的情况),大量输入总是会填满内存。 - mostar

0
或者使用egrep与一个分离元素:
egrep '(XXXX|YYYY)' FILE A | sort | uniq | ...

或者awk:

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

谢谢你的回答。我理解你的观点……但是我该如何将2个grep语句的结果存储在两个变量中? - User
你的输入数据有多大?这只对小数据量有意义。看看awk中的关联数组。 - mavam
输入数据在 200MB 的范围内。这是一个大文件。 - User
现在大多数机器都有超过200 MB的RAM,所以你可能没问题。如果输入数据超出了可用内存,你需要采用上述的管道和过滤器处理方法。 - mavam

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

这个程序在扫描文件时,每当看到一个包含适当模式的唯一行时就会增加计数器。请注意,在YYYY行数组迭代的顺序在这里没有明确定义,因此需要进行排序。某些awk版本提供了无需依赖外部实用程序即可对数组进行排序的功能,但并非所有版本都支持。如果要执行该操作,请使用perl。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接