2016-06-08 63 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