【问题标题】:javascript regex capturing parenthesesjavascript正则表达式捕获括号
【发布时间】:2013-10-31 23:52:32
【问题描述】:

在处理 javascript 正则表达式时,我并没有真正理解 capturing parentheses 的概念。我不明白为什么下面的例子需要括号

var x = "{xxx} blah blah blah {yyy} and {111}";
x.replace( /{([^{}]*)}/g , 
          function(match,content) {
               console.log(match,content);
               return "whatever";
});

//it will print
{xxx} xxx
{yyy} yyy
{111} 111

所以当我从模式x 中删除括号时,结果会给出不同的值

x.replace( /{[^{}]*}/g , 
          function(match,content) {
               console.log(match,content);
               return "whatever";
});

//it will print
{xxx} 0
{yyy} 37
{111} 49

所以内容值现在变成了我不知道为什么的数值。有人可以解释幕后发生的事情吗?

【问题讨论】:

  • 第二个代码将输出 0,21,31 这是匹配的索引(不是您提供的)

标签: javascript regex replace str-replace


【解决方案1】:

这对于替换文本很有用。

例如,我有这个字符串“一二三四”,我想像“四三二一”一样反转。为此,我将使用这行代码:

var reversed = "one two three four".replace(/(one) (two) (three) (four)/, "$4 $3 $2 $1");

注意 $n 如何表示字符串中的每个单词。

另一个例子:我有相同的字符串“一二三四”,我想将每个单词打印两次:

var eachWordTwice = "one two three four".replace(/(one) (two) (three) (four)/, "$1 $1 $2 $2 $3 $3 $4 $4");

【讨论】:

    【解决方案2】:

    括号仅用于捕获/替换匹配的一部分。例如,当我使用它来匹配可能有或没有分机的电话号码时。这个函数匹配整个字符串(如果if 是正确的),所以整个字符串被替换,但我只是使用特定类型的字符以特定的顺序,带有空格或其他(“()-x”)输入中允许的字符。

    如果给定 6512589631x1234 或 1 651 258 9631 1234,它将始终输出格式为 (651) 258-9631 x1234 的字符串。它也不允许(或在这种情况下为格式)免费电话号码,因为它们不是允许在我的领域。

    function phoneNumber(v) {
    // take in a string, return a formatted string (651) 651-6511 x1234
    if (v.search(/^[1]{0,1}[-(\s.]{0,1}(?!800|888|877|866|855|900)([2-9][0-9]{2})[-)\s.]{0,2}([2-9][0-9]{2})[-.\s]{0,2}([0-9]{4})[\s]*[x]{0,1}([0-9]{1,5}){1}$/gi) !== -1) {return v.replace(/^[1]{0,1}[-(\s.]{0,1}(?!800|888|877|866|855|900)([2-9][0-9]{2})[-)\s.]{0,2}([2-9][0-9]{2})[-.\s]{0,2}([0-9]{4})[\s]*[x]{0,1}([0-9]{1,5}){1}$/gi,"($1) $2-$3 x$4"); }
    if (v.search(/^[1]{0,1}[-(\s.]{0,1}(?!800|888|877|866|855|900)([2-9][0-9]{2})[-)\s.]{0,1}([2-9][0-9]{2})[-.\s]{0,2}([0-9]{4})$/gi) !== -1) { return v.replace(/^[1]{0,1}[-(\s.]{0,1}(?!800|888|877|866|855|900)([2-9][0-9]{2})[-)\s.]{0,1}([2-9][0-9]{2})[-.\s]{0,2}([0-9]{4})$/gi,"($1) $2-$3"); }
    return v;
    }
    

    这允许我收集区号、前缀、行号和可选的扩展名,并按照我需要的方式对其进行格式化(例如,对于无法按照指示进行操作的用户)。

    因此,如果您输入 6516516511x1234 或“(651) 651-6511 x1234”,它将匹配此示例中的一个或另一个正则表达式。

    现在您的代码中发生的事情就像@amine-hajyoussef 所说的那样 - 正在返回每个匹配项的开始索引。 match 例如一个(返回的文本)或search 为索引提供更好的服务,如示例二所示。 p.s.w.g's 答案扩大。

    【讨论】:

      【解决方案3】:

      数字:

      匹配的子字符串在总字符串中的偏移量是 检查。 (例如,如果总字符串是“abcd”,并且 匹配的子字符串为“bc”,则此参数将为 1。)

      来源:

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

      “将函数指定为参数”部分

      【讨论】:

        【解决方案4】:

        根据MDN documentation,函数的参数将依次为:

        • 匹配的子字符串。
        • 已定义的任何组(如果有)。
        • 在原始字符串中找到匹配项的索引。
        • 原始字符串。

        所以在第一个示例中,content 将是在组 1 中捕获的字符串。但是当您在第二个示例中删除组时,content 实际上是找到匹配项的索引。

        【讨论】:

        • 这是一个愚蠢的接口(允许中间的可变参数),但它就是这样......这个答案解释了观察到的行为。
        • function(match, p1, offset, string) 是 /{([^{}]*)}/g 的正确函数,而 function(match, offset, string) 是正确的函数对于 /{[^{}]*}/g。希望这是有道理的。
        猜你喜欢
        • 2012-04-13
        • 1970-01-01
        • 1970-01-01
        • 2015-01-20
        • 1970-01-01
        • 2020-02-21
        • 1970-01-01
        • 1970-01-01
        • 2013-06-17
        相关资源
        最近更新 更多