执行后
grep '[a-z]\{22\}' /usr/share/dict/words
输出是
counterrevolutionaries
electroencephalographs
但在执行时
grep '[^a-z]\{22\}' /usr/share/dict/words
没有输出。
我预计它会产生与
grep -v '[a-z]\{22\}' /usr/share/dict/words
我的问题是出了什么问题以及为什么?
答案1
[specification]
匹配排序元素(可以是区域设置排序算法中定义的字符或字符序列(例如,在 GNU 系统上的匈牙利语言环境中,是在和dzs
之间排序的排序元素))d
e
指定的放。
该规范可以包括
- 像
a-z
(或) 这样的范围用于整理在和[.dzs.]-z
之间整理的元素(请注意,它通常包括 abcdefghijklmnoprstuvwxyz,但在大多数语言环境中,它包括更多内容)。此外,由于 POSIX 未指定除 POSIX 语言环境之外的其他语言环境,因此这些范围基于排序规则顺序的程度在不同实现之间存在显着差异。a
z
- 单个字符或整理元素 (
x
,[.dsz.]
) - POSIX 字符类
[:alpha:]
,[:digit:]
- 等效类,例如
[=e=]
具有相同主要整理权重的所有整理元素e
(可能包括诸如é
)
因此,例如,[acd[=e=]h-k[:digit:][.dzs.]]
如果整理元素上的匹配项是a
、c
、d
或dzs
等于e
或 在 和 之间进行整理h
,k
或 则分类为数字。
如果规范以 开头^
,那么它仍然匹配一个整理元素,但对集合进行补充。这是除指定元素之外的任何整理元素。
因此,[^a-z]
匹配任何不在a
和之间进行整理的整理元素z
。例如,它可能会匹配 on1
和ẑ
,可能匹配X
或DSZ
取决于语言环境和grep
实现,但不会匹配 on a
,x
也不会匹配z
,也可能不会匹配 on é
。
所以grep '[^a-z]\{22\}'
匹配的行包含在 之前或之后22
进行整理的整理元素序列。a
z
Whilegrep -v '[a-z]\{22\}'
匹配不包含在a
和之间进行整理的 22 个整理元素序列的行z
。
匹配相同的元素-v
几乎不可能实现,您需要匹配[a-z]
两个元素之间包含不超过 21 个排序元素的行[^a-z]
。但如果语言环境支持多字符整理元素,那实际上是不可能的。例如,在那些匈牙利语言环境中,[a-z]
匹配 ondsz
但也匹配d
, s
,z
因此您会发现在那里,[a-z]{0,21}
将匹配 ondszxxxyyyxxxyyyxxxyyyx
但也匹配[a-z]{22}
。
对于没有多字符整理元素的区域设置,您可以执行以下操作:
grep '^[^a-z]*\([a-z]\{1,21\}[^a-z]\{1,\}\)*[a-z]\{0,21\}$'
现在,还有一些grep
实现支持更高级的正则语法,其中的选项具有一些否定操作员。
例如,GNU 或 ast-open 实现grep
支持类似 perl(在 GNU grep 中使用 libpcre,ast-open 自己的 ast-open grep 实现)正则表达式,-P
其选项具有(?!pattern)
负前瞻运算符。
(?!pattern)
如果模式从那里开始不匹配,则在主题字符串的任何点上以零宽度进行匹配。所以人们可以使用:
grep -P '^(?!.*[a-z]{22})'
匹配行的开头,前提是后面没有任何数量的字符和 22[a-z]
秒。但请注意,在 PCRE 中(不在 ast-open 中),[a-z]
仅匹配 abcdefghijklmnopqrstuvwxyz,无论区域设置如何。
ast-open 还可以选择-X
他们所说的选项增强的正则表达式。这些增强的正则表达式有一个!
否定事物的运算符。x!
将匹配除x
(包括空字符串)之外的任何内容。
因此,使用 ast-open grep
,您还可以执行以下操作:
grep -X '^(.*[a-z]{22}.*)!$'
答案2
grep '[^a-z]\{22\}' /usr/share/dict/words
查找文件中
/usr/share/dict/words
包含非小写字母的 22 个字符的字符串的行。该文件很可能不包含任何此类行。 (为什么该文件包含 22 个非字母的字符串?)grep -v '[a-z]\{22\}' /usr/share/dict/words
查找不包含 22 个字母的字符串的行。可能会有很多这样的线路。 (因为大多数单词都少于 22 个字母。)