【问题标题】:Break out of replace global loop打破替换全局循环
【发布时间】:2014-02-21 13:05:36
【问题描述】:

我有一个正则表达式,用全局集进行字符串替换。我只需要一个替换,但我使用的是全局的,因为有第二组模式匹配(一个确定替换开始时可接受的索引的数学方程)我不能轻易地表达为正则表达式的一部分。

var myString = //function-created string
myString = myString.replace(myRegex, function(){
    if (/* this index is okay */){

        //!! want to STOP searching now !!//
        return //my return string

    } else {
        return arguments[0];
        //return the string we matched (no change)
        //continue on to the next match
    }
}, "g");

如果可能的话,我该如何跳出字符串全局搜索?

谢谢

可能的解决方案

一种解决方案(出于性能原因,在我的场景中不起作用,因为我有非常大的字符串,其中有数千个可能匹配非常复杂的 RegExp 运行数百或数千次):

var matched = false;
var myString = //function-created string
myString = myString.replace(myRegex, function(){
    if (!matched && /* this index is okay */){
        matched = true;
        //!! want to STOP searching now !!//
        return //my return string

    } else {
        return arguments[0];
        //return the string we matched (no change)
        //continue on to the next match
    }
}, "g");

【问题讨论】:

  • 我不知何故错过了您的正则表达式以及简单的输入和预期输出示例
  • 你能先match他们,然后循环浏览这些吗?
  • @Wrikken 从技术上讲这可能有效,但它会影响性能。我添加了一个可能的解决方案,它可以匹配所有内容(类似于您所说的),但是在我的场景中的性能影响非常苛刻。
  • @RandyHall:如果性能有问题,那么也许你需要重新考虑你这样做的方式。全局选项将匹配所有可能的匹配,这就是它的用途,没有办法提前退出。如果只需要匹配一次,请不要使用g。所以也许你最好弄清楚为什么你觉得你需要g,以及是否有更好的方法来处理它。
  • 如果您甚至想停止解析字符串的其余部分以进行匹配,您可以编写该解析器并用勺子喂它增加输入的部分,并在找到它时停止解析。或者您可以省略 guse the match.index 以从输入中删除匹配项,如果它们不符合您的数学检查,直到找到符合要求的匹配项。

标签: javascript regex replace global break


【解决方案1】:

请改用RegExp.exec()。由于您只进行一次替换,因此我利用这一事实来简化替换逻辑。

var myString = "some string";
// NOTE: The g flag is important!
var myRegex = /some_regex/g;

// Default value when no match is found
var result = myString;
var arr = null;

while ((arr = myRegex.exec(myString)) != null) {
    // arr.index gives the starting index of the match
    if (/* index is OK */) {
        // Assign new value to result
        result = myString.substring(0, arr.index) +
                 /* replacement */ +
                 myString.substring(myRegex.lastIndex);
        break;
    }

    // Increment lastIndex of myRegex if the regex matches an empty string
    // This is important to prevent infinite loop
    if (arr[0].length == 0) {
        myRegex.lastIndex++;
    }
}

此代码表现出与String.match() 相同的行为,因为它还increments the index by 1 if the last match is empty 以防止无限循环。

【讨论】:

    【解决方案2】:

    我质疑你关于性能的逻辑。我认为在 cmets 中提出的一些观点是有效的。但是,我知道什么... ;)

    但是,这是做你想做的事情的一种方式。同样,我认为这在性能方面并不是最好的......:

    var myString = "This is the original string. Let's see if the original will change...";
    var myRegex = new RegExp('original', 'g');
    var matched=false;
    
    document.write(myString+'<br>');
    
    myString = myString.replace(myRegex, function (match) {
    
        if ( !matched ) {
    
            matched = true;
            return 'replaced';
    
        } else {
            return match;
        }
    });
    
    document.write(myString);
    

    这很像您的“可能的解决方案”。并且在替换后它不会“中止”(因此我的性能保留)。但它可以满足您的要求。它替换第一个实例,设置一个标志,然后返回匹配的字符串。

    看到它工作here

    问候。

    【讨论】:

      【解决方案3】:

      你可以把try-catch和使用未声明的变量退出替换功能

      var i = 0;
      
      try{
       "aaaaa".replace ( /./g, function( a, b ){
      
        //Exit the loop on the 3-rd iteration
        if ( i === 3 ){
      
         stop; //undeclared variable
      
        }
      
        //Increment i
        i++
      
       })
      
      }
      catch( err ){
      }
      
      alert ( "i = " + i ); //Shows 3
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-28
        • 2021-03-11
        • 2018-02-28
        • 2021-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多