我想更改以下命令,以便正则表达式匹配 /usr/share/dict/words 中包含的单词确切地3 a 代替至少3个a。
cat /usr/share/dict/words | grep "a.*a.*a" | grep -v "'s$" | wc -l
我该怎么做呢?
答案1
这是使用[^a]
(匹配除 之外的任何字符a
) 而不是.
(匹配任何字符) 的一种方法:
$ grep -E '^([^a]*a){3}[^a]*$' /usr/share/dict/cracklib-small | shuf -n 4
areaway
humanitarian
capitalizations
autonavigator
您也可以像这样编写正则表达式,^[^a]*(a[^a]*){3}$
得到相同的结果。
当您需要不同数量的 a 时,它也相当于^[^a]*a[^a]*a[^a]*a[^a]*$
无法缩放。虽然性能要好得多,但这并不重要,除非您正在处理千兆字节的数据。
您还可以使用隐式执行此操作的选项,而不是显式使用^
和regexp 锚运算符。另请参阅不区分大小写匹配的选项(根据区域设置):$
-x
-i
grep -xiE '([^a]*a){3}[^a]*'
答案2
使用相同类型的模式来检测“至少 4 a
s”,并反转匹配的含义:
grep 'a.*a.*a' /usr/share/dict/words | grep -v 'a.*a.*a.*a'
或者,
grep '\(a.*\)\{3\}' /usr/share/dict/words | grep -v '\(a.*\)\{4\}'
或者,
grep -E '(a.*){3}' /usr/share/dict/words | grep -v -E '(a.*){4}'
或者,使用awk
witha
作为字段分隔符并对字段进行计数:
awk -F a 'NF == 4' /usr/share/dict/words
(在具有三个 s 的行上a
,将有四个字段)
或者,使用 Perl 的运算符来计算每行上 str
的数量:a
perl -ne 'print if (tr/a/a/ == 3)' /usr/share/dict/words
该运算符返回进行的音译次数,我们将每个音译替换a
为另一个a
,因此实际输出不会被修改。