0

我正在尝试使用正则表达式替换,并且需要一些帮助来理解 $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美元)感到困惑。谢谢!

4

4 回答 4

2

($1) 有什么条件?

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

我猜想,在这种情况下,它会将空字符串评估为假,将非空字符串评估为真——但由于您没有告诉我们这是什么语言,因此无法确定。

于 2013-09-08T22:00:47.480 回答
1

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

于 2013-09-08T21:58:49.067 回答
1

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

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),因为对于正则表达式,它永远不会是真实的(它将是第一个或第二个交替子表达式)。

于 2013-09-08T22:03:58.730 回答
0

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

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

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

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

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

于 2018-02-01T18:59:12.133 回答