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

sha*_*n11 3 grep regular-expression

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

小智 7

此规则“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
Run Code Online (Sandbox Code Playgroud)

这是一个更短但由于嵌套而难以遵循的:

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]))
Run Code Online (Sandbox Code Playgroud)

两者都假设您要搜索的单词位于每行一个单词的文件中。如果没有,您必须将所有.'s 更改[^ ]为匹配非空格字符。(注意:\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]*)$
Run Code Online (Sandbox Code Playgroud)

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

grep -E '^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$' wordlist
Run Code Online (Sandbox Code Playgroud)

和方便的-v选项给你,你的话想:

grep -vE '^([^a]*|[^e]*|[^i]*|[^o]*|[^u]*)$' wordlist
Run Code Online (Sandbox Code Playgroud)

-i如果需要,请添加。

在编写正则表达式时,需要牢记反转技术。有时,一个非常复杂的正则表达式是一个更简单的正则表达式的反面。

  • 惊人的。从托儿所回来,我一直在考虑使用“printf”和“printf”。`-v` 没有 * 发生在我身上。不过有一件事 - 我想你可能想要像 `[^ ]*` 而不是 `.*`。那将是我的重大启示...... *叹气* (2认同)