这个Perl正则表达式的含义是什么?

3
the regex expression is as below:
if ($ftxt =~ m|/([^=]+)="(.+)"|o)
   {
    .....
   }

这个正则表达式似乎与其他许多正则表达式不同。让我困惑的是“|”,大多数正则表达式使用“/”而不是“|”。还有,组([^=]+)也让我感到困惑。我知道 [^=] 表示“字符串的开头”或“=” ,但是重复“^”一次或多次是什么意思?如何解释这个呢?


1
你对[^=]的理解是错误的。在正则表达式中,方括号表示匹配单个字符的类别,并且在开头的^表示否定该类别。在方括号内部,^则表示字面上的字符(而许多其他字符在方括号内部失去了它们的特殊含义)。如果没有方括号,^=将匹配行首的等号。 - Benoit
请使用YAPE::Regex::Explain来解释这个正则表达式给我听。 - Sinan Ünür
3个回答

6

您可以使用不同的分隔符替代 /。例如,您可以使用:

m#/([^=]+)="(.+)"#o

或者

m~/([^=]+)="(.+)"~o

使用与/不同的内容的优点在于您无需转义斜杠,否则您需要使用:
m/\/([^=]+)="(.+)"/o
  ^
([^=]+)是一个捕获组,里面包含了[^=]+[^=]是一个否定类,将匹配任何不是等于号的字符。
在字符类开头,^的行为与字符类外部不同,它不是指'行首'。
至于最后一部分o,这是一个标志,我之前没有遇到过,所以进行了一些搜索,找到了这篇帖子,引用如下:

/o修改符在perlop文档中而不是perlre文档中,因为它是引用样式修改符而不是正则表达式修改符。 这对我来说总是很奇怪,但事实就是这样。

在Perl 5.6之前,即使变量未更改,Perl也会重新编译正则表达式。 现在您无需这样做。 您可以使用/o,尽管变量有进一步的更改,也可以只编译正则表达式一次,但正如其他答案所指出的那样,qr//更好。


4
  1. 一些正则表达式实现允许您使用除 / 以外的其他特殊字符作为分隔符。如果您需要在正则表达式本身中使用该特殊字符,则不必对其进行转义,这很有用。(/ 本身在正则表达式语法中并不是特殊字符,但如果它在主机语言的正则表达式字面量语法中使用,则需要转义。)Perl的引号运算符的文档提到了这一点。

  2. 这是教程级别的内容:方括号([abc])表示一个字符类——它意味着“方括号内的任何字符”。(在我的示例中,它意味着“要么是 a,要么是 b,要么是 c。”)在它们内部,^ 特殊字符具有不同的含义,它反转字符类。因此,[^=] 表示“除 = 外的任何字符”,[^=]+ 表示“一个或多个不是 = 的字符”。


引用Perl的正则表达式语法文档中的内容:
您可以通过将一组字符括在[]中来指定字符类,这将匹配列表中的任何字符。如果“ [”后的第一个字符是“ ^”,则该类匹配不在列表中的任何字符。

2
它的目的是匹配类似方程式的表达式,将键和值分别捕获。想象一下你有一个语句,像 height="30px",你想捕获 height 属性名称以及它的值 30px

所以你有 m|/([^=]+)="(.+)"|

关键是在遇到等号之前捕获所有内容。因此使用 [^=] 进行捕获。当作为 [] 括号中的第一个字符时,^ 是一个否定元字符。这意味着它将匹配除了你想要的 = 之外的任何字符。/ 可能是一个错误,如果你需要捕获组,则不应使用它,或者如果确实打算如此,则意味着要匹配一个括号。由于它是一个特殊字符,所以需要进行转义,这就是为什么使用 \(。如果你想捕获组,它应该是 ([^=]+)

接下来是等号符号,你不在乎它。然后是包含值的引号。所以你可以像 "(.+)" 这样去捕获它。 .+ 会贪婪地匹配每个字符,包括最后一个 "。但是然后它会发现无法在正则表达式中匹配最后一个 ",所以它会回溯,放弃正则表达式 (.+) 捕获的最后一个 ",这样就留下了引号内的字符串以在组中捕获。现在你可以通过 $1$2 访问键和值。酷毙了,不是吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接