为什么正则表达式中的 ^s$ 不匹配“以 s 开头,以 s 结尾”这样的字符串?

Ask*_*321 4 awk text-processing regular-expression

如果^匹配一行的开头并$匹配一行的结尾,那么为什么不像^$标题中的那样匹配字符串的开头和结尾?

你如何制作这样一个匹配这样的字符串的正则表达式:

starts with s and ends with s
Run Code Online (Sandbox Code Playgroud)

Adm*_*Bee 44

原因在于 RegEx 匹配的处理方式(参见此处,例如):字符串从左到右求值,并且 - 除了反向引用 - 字符串中的每个符号都必须与正则表达式中的标记匹配(即在最简单的情况下是文字符号本身),尽管由于重复运算符,标记可以是隐式的。

关键是正则表达式不描述“整个字符串的一般属性”(例如“以”开头和结尾s),而是对字符串的字符级别强加规则。所以,你的正则表达式

^s$
Run Code Online (Sandbox Code Playgroud)

意思是:“字符串开头”,后跟 s,紧接着是“字符串结尾”。因此,这只会匹配由单个字母组成的字符串s。虽然从技术上讲这是一个以 开头和结尾的字符串s,但它不是您要查找的内容。

如果要匹配以 开头、中间s包含任意字符并以 结尾的字符串,则s必须明确指定所有这些。

使其非常明确:

  • 第一次迭代可能如下所示:
    ^s.*s$
    
    Run Code Online (Sandbox Code Playgroud) 这将匹配“以 开头的字符串s,后跟零个或多个任何类型的字符 ( .*),后跟s在字符串末尾。
  • 当然,这不会匹配由字符组成的字符串s。因此,在第二次迭代中,我们会将初始之后的部分s设为可选(请参阅 @user414777 的评论):
    ^s(.*s)?$
    
    Run Code Online (Sandbox Code Playgroud) 这将匹配“以 开头的字符串s,后跟零次或一次 (the ?) ' 零个或多个任意类型字符的子字符串,后跟一个s'( 的内容(...)),并紧随其后”。

现在,当您用 标记您的问题时awk,这可能意味着您想要为awk仅当行或字符串以 开头和结尾才适用的规则创建条件s。这可能看起来像:

awk '/^s/ && /s$/ { ... }'
Run Code Online (Sandbox Code Playgroud)

使用grep,这样的AND构造本身是不可能的(语法相当于OR),但您可以通过管道实现它:-e regex1 -e regex2

grep "^s" sourcefile.txt | grep "s$"
Run Code Online (Sandbox Code Playgroud)

  • @AdminBee 你是对的。它需要是两个带有管道的“grep”。 (6认同)
  • 这是一个很好的例子,使用两个单独的正则表达式比使用一个单独的表达式更容易(因为更容易理解和更容易维护)。您在结尾处的 `awk` 示例很好地说明了这一点。使用`grep`,你会做`grep -e '^s' -e 's$'`。 (5认同)
  • @Kusalananda 你是对的,但你确定使用 `grep` 示例吗?在我的 GNU `grep` 中,指定两个模式相当于 OR,而不是 AND,因为 OP 要求...... (4认同)