2012-07-10 75 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,如果你想這樣做。