2016-06-08 21 views
1

我有以下問題,我需要從文件中檢索包含正好2元音(任意順序)的所有單詞。該文件每行只包含一個字。Grep單詞與確切的兩個元音

我的當前的解決方法是:

Grep1:檢索詞如earth, over, under, one...

grep -i "^[aeiou][^aeiou]*[aeiou][^aeiou]*$" genesis.words > A.txt 

Grep2:檢索詞如formless, deep, said...

grep -i "^[^aeiou][^aeiou]*[aeiou][^aeiou]*[aeiou][^aeiou]*$" genesis.words > B.txt 

上述解決方案的工作原理,但是當我將兩個正則表達式連接成一個正則表達式時,什麼都不返回!

Grep1的母親& Grep2:應該檢索一切!

grep -i "^[aeiou][^aeiou]*[aeiou][^aeiou]*$|^[^aeiou][^aeiou]*[aeiou][^aeiou]*[aeiou][^aeiou]*$" genesis.words 

我認爲問題是在我的表達實現的^$但試圖DIFF版本沒有sucess!

任何幫助將不勝感激!

OS是AIX 6100-09-04-1441

回答

1

你接近這個應該工作:

grep -i "^[^aeiou]*[aeiou][^aeiou]*[aeiou][^aeiou]*$" genesis.words > A.txt 

所以應該找到所有八種可能性(兩個元音確定3個nonvowel序列,每個可能爲空; 2^3 8):

 [ ]I[ ]o[ ] 
    [ ]e[ ]a[r] 
    [ ]e[r]a[ ] 
    [ ]e[l]a[n] 
    [T]e[ ]a[ ] 
    [D]e[ ]a[r] 
    [D]e[w]a[r] 
    [D]a[w]a[ ] 
    [H]a[w]a[y] 

至於連接,需要轉義。您可以使用一個錨:

^(regexp1\|regexp2)$ 
+0

謝謝!你的解決方案就像一個魅力!至於連接我應用你的建議,但仍然沒有返回。 – Altons

1

由於*可以匹配0次或更多,你應該能夠與[^aeiou]*開始字符串:儘量

"^[^aeiou]*[aeiou][^aeiou]*[aeiou][^aeiou]*$" 

至於固定您的正則表達式,我認爲你需要逃出酒吧爲\|,所以

grep -i "^[aeiou][^aeiou]*[aeiou][^aeiou]*$\|^[^aeiou][^aeiou]*[aeiou][^aeiou]*[aeiou][^aeiou]*$" genesis.words 
1

如果你不介意Perl,你可以使用這個:

perl -lne '$m=$_; tr/[aeiou]//cd; print $m if length()==2;' /usr/share/dict/words 

說... 「保存當前行(單詞)在$ m。刪除所有不是元音的東西。如果有兩件事情(即元音)左打印的原話。」我使用該系統的字典作爲我的測試中輸入

注意

你可以做幾乎同樣的事情在awk

+0

這說明了爲什麼'Perl'有時是一種非常棒的語言! +1你提到過'awk',但是有沒有優勢互相搭配? –

+1

我想,至少對我來說,Perl的優勢在於它在Linux,Unix,OSX,Windows中完全一樣 - 只有一種標準的正則表達式語法,只有一種一致的文件命名約定,一套標準化的行結尾,一種轉義集,只有一個日期語法,只有一個'find'語法,它可以完成'tr'所能做的所有事情,''sed','awk'可以做的所有事情,'grep','fgrep',CPAN ... –

1

如果你能使用替代到grep trwc效果很好:

words=/path/to/words.txt 

while read -e word ; do 
    v=$(echo $word | tr -cd 'aeiou' | wc -c) 
    [[ ! $v -eq "2" ]] || echo $word >> output.txt 
done < $words 

這逐行讀取原始文件行,計數元音&返回只有2到output.txt的結果。

+0

感謝diff方法 - 沒有想過這種方式,但是因爲這通常是從命令行運行(quick&dirty),grep在這個特定情況下是最好的選擇。 – Altons