正则表达式中的 $0 和 $1

$0 and $1 in Regular Expression

本文关键字:正则表达式      更新时间:2023-09-26

我正在尝试用正则表达式替换,需要一些帮助来理解 $1 在此代码中的含义。此代码用于交换大小写。

return str.replace(/([a-z])|([A-Z])/g,
    function($0, $1)
    { return ($1) ? $0.toUpperCase() : $0.toLowerCase(); })

了解在替换方法的第一个参数中,我检查我们是否有小写或大写字母,但我不明白拥有第二个参数的方式和作用。

我理解语法,如果($1)为真,我们执行$0.toUpperCase(),如果不是,我们执行$0.toLowerCase()。但是如何从如果($1)是真的中判断呢?($1)有什么条件?我想我明白 $0 是针对整个匹配的字符串。但我对($1)感到困惑。谢谢!

($1)有什么条件?

None -- 正则表达式语法不指定如何评估匹配组的真实性,因此这取决于包含语言的行为。

我猜,在这种情况下,它评估空字符串为假,非空字符串为真 - 但由于你没有告诉我们这是什么语言,所以无法确定。

请注意传递给计算器的参数。按照给定的模式,我将其重写为:

str.replace(/([a-z])|([A-Z])/g,
  function(match, p1, p2) {
    return p1 ? p1.toUpperCase() : p2.toLowerCase();
  })

如果([a-z])匹配,则绑定p1$1)变量的计算结果为真字符串(任何不为空的字符串;特别是正则表达式接受的字符串);否则p1将是空字符串""(这是一个假值)。这就是为什么对p1$1)的检查是正确的 - 请注意,绑定的捕获组始终具有字符串类型。

请注意,检查match$0)是没有意义的,因为它永远不会与正则表达式(它将是第一个或第二个交替子表达式)无关。

$0确实是整个匹配的字符串。 $1是第一个子模式(即小写字母)。如果第一个子模式匹配,则将其大写,否则将其小写。应该注意的是,该函数被赋予了另一个参数,但在这种情况下不使用它。

此示例中的 $0 和 $1 只是变量(使用匈牙利表示法命名)。您可以轻松地将它们替换为 a 和 b,并且代码的工作方式相同。调用该函数时有许多参数。第一个参数是匹配的子字符串。第二个参数是第一个捕获(与第一个括号中的正则表达式匹配的任何内容,在本例中为单个小写字母 a-z)。第三个(缺失)参数将是第二个捕获(匹配大写字母 A-Z),但请注意,这将被忽略。

由于正则表达式使用全局"g"标志,因此该函数(可能)被调用多次。正则表达式匹配任何小写或大写字母。第一个函数参数将从 str 连续匹配每个字符,仅当第一个捕获组匹配时才设置第二个参数 - 这意味着仅当字符为小写时才设置第二个函数参数。如果设置了第二个参数(即这是一个小写字符),则在匹配项上调用 toUpperCase 函数。如果未设置第二个参数(即这是一个大写字符),则在匹配项上调用 toLowerCase 函数。在后一种情况下,未使用的第三个参数包含第二个捕获组内容。

整个解决方案具有逐个字符交换案例的效果。

但是..在这段代码中使用$0和$1表明创建者正在玩弄其他东西:引用和反向引用。 $0(或某些语言中的''0)是对匹配的引用(即它恰好是函数的第一个参数),$1(或''1)是对第一个捕获组的引用,等等。此代码的作者这样命名变量,以支持第一个参数等效于 $0 和第二个参数等效于 $1 等的概念。在我看来,这是开明的,完全令人困惑。使用这些变量名称表明一些神奇的事情正在发生。匈牙利符号的使用也暗示了其他东西。这里没有什么神奇之处,因此变量应该更简单地命名 - 匹配和is_lowercase就可以了。

此外,由于缺少第三个函数参数,因此无需捕获大写字符类。