我试图了解正则表达式在命令(^[0-9]..[a-zA-Z ]+$)
中检测到的表达式(Linux 终端)grep
我知道如果我写以下命令:
grep ^[0-9]..[a-zA-Z] filename.txt
我将检测任何包含表达式的行,例如92afg
但我不确定其含义+$
以及我能够使用命令检测到哪种表达式
grep ^[0-9]..[a-zA-Z]+$ filename.txt
我尝试打开一个新的文本文件,然后仅键入我认为会被检测到的表达式,但它们都不匹配,因此我希望对此进行解释。
答案1
让我们分解一下。首先,请注意,此 RegExp 使用“扩展正则表达式”语法 (ERE) -+
是一个元字符,在默认使用的“基本正则表达式”语法中不起作用grep
(意味着它会匹配自身并需要在该位置使用文字+
),因此如果您想使用该正则表达式grep
,您将需要传递该-E
选项。
- 是
^
一个锚点,将正则表达式的这个位置与行的开头联系起来。 - 是
[0-9]
一个字符列表,将匹配属于和之间排序范围的任何单个(1)字符。具体包括什么取决于“排序顺序”,其中由环境变量决定。0
9
LC_COLLATE
- 匹配
.
任何单个字符,因此 2..
表示“任意两个字符”。 - 返回
[a-zA-Z]
是一个字符列表,将匹配位于和之间的字符(1),以及位于和之间的字符。同样,这意味着什么取决于整理顺序!a
z
A
Z
- 意思
+
是“之前的一个或多个” - 是
$
一个锚点,将正则表达式的这个位置连接到行尾。
所以,你的正则表达式旨在(1)匹配任何符合以下条件的行
- 以任意数字开头
- 后跟任意两个字符
- 并且只包含字母(但至少一个)直到行尾。
(1)对于它实际上可能做什么,请参见下文
一些笔记
在您的示例中,您使用不带引号的正则表达式。这意味着任何字符在传递给命令之前都可以由 shell 解释
grep
。如果您的模式包含$
或通配字符(*
、?
和[...]
字符列表!),shell 可能会尝试执行变量扩展(从而替换正则表达式的部分内容)或将通配模式扩展为可能的多个文件名,以便最终您将拥有更多参数在您最初想要的命令行上。 shell 特有的其他字符(>
、#
等;
)可能会导致更意外的行为。你应该使用grep -E '^[0-9]..[a-zA-Z]+$' filename.txt
反而。请注意,您可以通过使用该
-x
标志强制“整行”匹配来摆脱开始和结束锚点:grep -x -E '[0-9]..[a-zA-Z]+' filename.txt
包含范围(例如
a-z
)的字符列表是危险的因为他们可能不会给你你的想法。天真的人们可能期望它们匹配 ASCII 表中起始字符和结束字符之间的所有字符,但这仅适用于区域设置C
。在其他语言环境中(特别是在通常设置的系统语言环境中,例如en_US.UTF-8
),排序规则类似于aAbB ... zZ
soa-z
也会匹配大多数大写字母。此外,匹配实际上不是在单个字符的级别上,而是在“排序规则元素”级别上,这意味着在某些语言环境中,甚至几个字母的组合可能匹配(例如dzs
匈牙利语)!看这个答案(或者,一般来说,@Stéphane Chazelas 关于模式匹配的大多数答案)以获得更多见解。如果您想确保范围有效,请至少通过以下方式设置给定命令的排序规则LC_COLLATE="C" grep -E ' ... ' filename.txt
答案2
+
代表“前一个或多个重复”,$
是“行尾”。请注意与 with 的区别,*
意思是“零次或多次重复”。
所以它基本上意味着:任何以数字开头的行,后跟任何类型的两个字符,然后是一个或多个(可能是大写)字母1,直到该行结束。
(请注意,某些语言环境可能不仅包含您期望的 AZ 或 az 中的 26 个字母,例如è
或ŷ
取决于语言)
有关正则表达式的良好指南,我强烈建议格里莫尔的美丽网站,我也衷心推荐例如sed
和awk
。
为什么不匹配?
+
是扩展正则表达式的一部分(否则被解释为文字+
- 符号)。
因此,要用作+
“一次或多次重复”,请使用-E
- 标志grep
并引用正则表达式,以避免 shell 特殊字符出现任何问题:
grep -E '^[0-9]..[a-zA-Z]+$' filename.txt