grep 查找包含所有元音的单词

grep 查找包含所有元音的单词

使用grep -E正则表达式,我需要查找包含一组不按特定顺序排列的所有字符的单词。例如,包含所有元音 (aeiou) 的单词,但元音可以以任何顺序出现在单词中。

答案1

该规则“以某种顺序包含所有内容aeiou”无法用grep -E合理大小的 POSIX 扩展正则表达式 ( ) 来表达。

这是一个大的列表,列出了 aeiou 的所有 120 种排列作为替代方案:

a.*e.*i.*o.*u|a.*e.*i.*u.*o|a.*e.*o.*i.*u|a.*e.*o.*u.*i|a.*e.*u.*i.*o|a.*e.*u.*o.*i|a.*i.*e.*o.*u|a.*i.*e.*u.*o|a.*i.*o.*e.*u|a.*i.*o.*u.*e|a.*i.*u.*e.*o|a.*i.*u.*o.*e|a.*o.*e.*i.*u|a.*o.*e.*u.*i|a.*o.*i.*e.*u|a.*o.*i.*u.*e|a.*o.*u.*e.*i|a.*o.*u.*i.*e|a.*u.*e.*i.*o|a.*u.*e.*o.*i|a.*u.*i.*e.*o|a.*u.*i.*o.*e|a.*u.*o.*e.*i|a.*u.*o.*i.*e|e.*a.*i.*o.*u|e.*a.*i.*u.*o|e.*a.*o.*i.*u|e.*a.*o.*u.*i|e.*a.*u.*i.*o|e.*a.*u.*o.*i|e.*i.*a.*o.*u|e.*i.*a.*u.*o|e.*i.*o.*a.*u|e.*i.*o.*u.*a|e.*i.*u.*a.*o|e.*i.*u.*o.*a|e.*o.*a.*i.*u|e.*o.*a.*u.*i|e.*o.*i.*a.*u|e.*o.*i.*u.*a|e.*o.*u.*a.*i|e.*o.*u.*i.*a|e.*u.*a.*i.*o|e.*u.*a.*o.*i|e.*u.*i.*a.*o|e.*u.*i.*o.*a|e.*u.*o.*a.*i|e.*u.*o.*i.*a|i.*a.*e.*o.*u|i.*a.*e.*u.*o|i.*a.*o.*e.*u|i.*a.*o.*u.*e|i.*a.*u.*e.*o|i.*a.*u.*o.*e|i.*e.*a.*o.*u|i.*e.*a.*u.*o|i.*e.*o.*a.*u|i.*e.*o.*u.*a|i.*e.*u.*a.*o|i.*e.*u.*o.*a|i.*o.*a.*e.*u|i.*o.*a.*u.*e|i.*o.*e.*a.*u|i.*o.*e.*u.*a|i.*o.*u.*a.*e|i.*o.*u.*e.*a|i.*u.*a.*e.*o|i.*u.*a.*o.*e|i.*u.*e.*a.*o|i.*u.*e.*o.*a|i.*u.*o.*a.*e|i.*u.*o.*e.*a|o.*a.*e.*i.*u|o.*a.*e.*u.*i|o.*a.*i.*e.*u|o.*a.*i.*u.*e|o.*a.*u.*e.*i|o.*a.*u.*i.*e|o.*e.*a.*i.*u|o.*e.*a.*u.*i|o.*e.*i.*a.*u|o.*e.*i.*u.*a|o.*e.*u.*a.*i|o.*e.*u.*i.*a|o.*i.*a.*e.*u|o.*i.*a.*u.*e|o.*i.*e.*a.*u|o.*i.*e.*u.*a|o.*i.*u.*a.*e|o.*i.*u.*e.*a|o.*u.*a.*e.*i|o.*u.*a.*i.*e|o.*u.*e.*a.*i|o.*u.*e.*i.*a|o.*u.*i.*a.*e|o.*u.*i.*e.*a|u.*a.*e.*i.*o|u.*a.*e.*o.*i|u.*a.*i.*e.*o|u.*a.*i.*o.*e|u.*a.*o.*e.*i|u.*a.*o.*i.*e|u.*e.*a.*i.*o|u.*e.*a.*o.*i|u.*e.*i.*a.*o|u.*e.*i.*o.*a|u.*e.*o.*a.*i|u.*e.*o.*i.*a|u.*i.*a.*e.*o|u.*i.*a.*o.*e|u.*i.*e.*a.*o|u.*i.*e.*o.*a|u.*i.*o.*a.*e|u.*i.*o.*e.*a|u.*o.*a.*e.*i|u.*o.*a.*i.*e|u.*o.*e.*a.*i|u.*o.*e.*i.*a|u.*o.*i.*a.*e|u.*o.*i.*e.*a

这是一个更短的代码,但由于嵌套而更难理解:

a.*(e.*(i.*[ou]|o.*[iu]|u.*[io])|i.*(e.*[ou]|o.*[eu]|u.*[eo])|o.*(e.*[iu]|i.*[eu]|u.*[ei])|u.*(e.*[io]|i.*[eo]|o.*[ei]))|e.*(a.*(i.*[ou]|o.*[iu]|u.*[io])|i.*(a.*[ou]|o.*[au]|u.*[ao])|o.*(a.*[iu]|i.*[au]|u.*[ai])|u.*(a.*[io]|i.*[ao]|o.*[ai]))|i.*(a.*(e.*[ou]|o.*[eu]|u.*[eo])|e.*(a.*[ou]|o.*[au]|u.*[ao])|o.*(a.*[eu]|e.*[au]|u.*[ae])|u.*(a.*[eo]|e.*[ao]|o.*[ae]))|o.*(a.*(e.*[iu]|i.*[eu]|u.*[ei])|e.*(a.*[iu]|i.*[au]|u.*[ai])|i.*(a.*[eu]|e.*[au]|u.*[ae])|u.*(a.*[ei]|e.*[ai]|i.*[ae]))|u.*(a.*(e.*[io]|i.*[eo]|o.*[ei])|e.*(a.*[io]|i.*[ao]|o.*[ai])|i.*(a.*[eo]|e.*[ao]|o.*[ae])|o.*(a.*[ei]|e.*[ai]|i.*[ae]))

这两者都假设您要搜索的单词位于每行一个单词的文件中。如果没有,您必须将所有的.' 更改为[^ ]匹配非空格字符。 (注意:\Sfrom perl 可在许多正则表达式引擎中使用,可能包括您使用的 grep,但与 perl 兼容的正则表达式不是标准 grep 功能,所以[^ ]它必须是。)

我不会尝试手动编写这些正则表达式。我在第一个代码中使用了排列生成器,并在 vim 中进行了大量的宏录制和重放来编写第二个代码。

但让我们看看如果我们把问题倒过来会发生什么。不要尝试匹配包含所有元音的字符串,而是尝试匹配相反的字符串:至少缺少一个元音

(从现在开始,我坚持输入中每行一个单词的假设。)

a缺少匹配项的单词^[^a]*$(从头到尾都是由 以外的字符组成a)。

e缺少匹配项的单词^[^e]*$
缺少i匹配项的单词^[^i]*$
缺少匹配o项的单词 缺少匹配项^[^o]*$
的单词u^[^u]*$

a缺少或缺少e或缺少i或缺少o或缺少u匹配项的单词

^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$

所以这个 grep 命令会给你所有你不想要的单词:

grep -E '^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$' wordlist

方便的-v选项为您提供了您想要的单词想:

grep -vE '^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$' wordlist

如果需要的话添加-i

编写正则表达式时要记住反转技术。有时,一个非常复杂的正则表达式是一个简单正则表达式的逆。

答案2

是否需要成为一个单身的 grep命令?要查找包含每个元音至少一次(以任何顺序)的所有单词,最简单的命令是

查询一个单词表| grep e | grep 我 | grep o |格列普你

-i如果需要不区分大小写,请添加。

答案3

在我看来,这是一个有点棘手的问题,因为grep它不具有真正的 AND 运算符。您可以使用各种技巧来grep部分获得 AND,但它仅在某些情况下有效。

例如,您可以使用通配符运算符来匹配具有您的模式的字符串,但只有当它的顺序与您的模式完全相同时,它才会匹配它。

样本文件

$ cat words.txt 
aeiou
a1e2i3o4u5
dog
blh
spkz
uoiea

1. 使用 .* 的示例

$ grep -E ".*a.*e.*i.*o.*u.*" words.txt 
aeiou
a1e2i3o4u5

aeiou这仅匹配具有同一级数中的序列的字符串。但它无法匹配uoiea

2. 使用 [aeiou] 的示例

$ grep -E [aeiou] words.txt 
aeiou
a1e2i3o4u5
dog
uoiea

这种方法可以匹配,但它太松散,匹配任何包含我们模式中至少 1 个字母的内容。

3. 使用多个 grep 的示例

$ grep a words.txt | grep e | grep i | grep o | grep u
aeiou
a1e2i3o4u5
uoiea

如果您被迫使用grep,并且您的目的是匹配一组中的所有字符,那么这实际上是您可用的唯一选项。

4. 使用 awk 的示例

$ awk '/a/ && /e/ && /i/ && /o/ && /u/ { print }' words.txt 
aeiou
a1e2i3o4u5
uoiea

就像处理 Unix 时经常出现的情况一样。如果您愿意改用合适的工具,看似不可能的任务就会变得容易。通过切换到,awk我们现在可以使用实际的 AND 运算符 ( &&),现在我们可以指定要查找的字符集。

grep5. 使用 的其他开关的示例(-w)

如果您匹配的字符串都保证是单个单词,您可以使用该-w开关。

   -w, --word-regexp
        Select only those lines containing matches that form whole words. 
        The test is that the matching substring must  either  be  at  the
        beginning  of  the  line,  or  preceded by a non-word constituent 
        character.  Similarly, it must be either at the end of the line or
        followed by a non-word constituent character.  Word-constituent 
        characters are letters, digits, and the underscore.

因此,只要该集合中的一系列字母[aeiou]都是连续的,您就可以像这样利用此开关:

$ grep -Ew "*[aeiou]*" words.txt 
aeiou
uoiea

但如果你必须处理多情况短语,那么它也会让你失败:

$ echo "I love Fort Lauderdale" | grep -Ew "*[aeiou]*" 
$

但是,如果我们使用不区分-i大小写的开关grep,那么它将再次起作用:

$ echo "I love Fort Lauderdale" | grep -Ewi "*[aeiou]*"
I love Fort Lauderdale

相关内容