什么表达式可以匹配 grep 命令中的模式 (^[0-9]..[a-zA-Z ]+$)? Linux bash

什么表达式可以匹配 grep 命令中的模式 (^[0-9]..[a-zA-Z ]+$)? Linux bash

我试图了解正则表达式在命令(^[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)字符。具体包括什么取决于“排序顺序”,其中由环境变量决定。09LC_COLLATE
  • 匹配.任何单个字符,因此 2..表示“任意两个字符”。
  • 返回[a-zA-Z]是一个字符列表,将匹配位于和之间的字符(1),以及位于和之间的字符。同样,这意味着什么取决于整理顺序!azAZ
  • 意思+是“之前的一个或多个”
  • $一个锚点,将正则表达式的这个位置连接到行尾。

所以,你的正则表达式旨在(1)匹配任何符合以下条件的行

  • 以任意数字开头
  • 后跟任意两个字符
  • 并且只包含字母(但至少一个)直到行尾。

(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
    
  2. 包含范围(例如a-z)的字符列表是危险的因为他们可能不会给你你的想法。天真的人们可能期望它们匹配 ASCII 表中起始字符和结束字符之间的所有字符,但这仅适用于区域设置C。在其他语言环境中(特别是在通常设置的系统语言环境中,例如en_US.UTF-8),排序规则类似于aAbB ... zZsoa-z也会匹配大多数大写字母。此外,匹配实际上不是在单个字符的级别上,而是在“排序规则元素”级别上,这意味着在某些语言环境中,甚至几个字母的组合可能匹配(例如dzs匈牙利语)!看这个答案(或者,一般来说,@Stéphane Chazelas 关于模式匹配的大多数答案)以获得更多见解。如果您想确保范围有效,请至少通过以下方式设置给定命令的排序规则

    LC_COLLATE="C" grep -E ' ... ' filename.txt
    

答案2

+代表“前一个或多个重复”,$是“行尾”。请注意与 with 的区别,*意思是“零次或多次重复”。

所以它基本上意味着:任何以数字开头的行,后跟任何类型的两个字符,然后是一个或多个(可能是大写)字母1,直到该行结束。

(请注意,某些语言环境可能不仅包含您期望的 AZ 或 az 中的 26 个字母,例如èŷ取决于语言)

有关正则表达式的良好指南,我强烈建议格里莫尔的美丽网站,我也衷心推荐例如sedawk


为什么不匹配?

+是扩展正则表达式的一部分(否则被解释为文字+- 符号)。

因此,要用作+“一次或多次重复”,请使用-E- 标志grep并引用正则表达式,以避免 shell 特殊字符出现任何问题:

grep -E '^[0-9]..[a-zA-Z]+$' filename.txt

相关内容