Javascript 正则表达式匹配所有不在引号内的实例

Javascript 正则表达式匹配所有不在引号内的实例,javascript,regex,escaping,quotes,Javascript,Regex,Escaping,Quotes,从中,我推断匹配给定正则表达式的所有实例(不在引号内)是不可能的。也就是说,它不能匹配转义引号(例如:“应该采用整个匹配”)。如果有一种我不知道的方法可以解决我的问题 然而,如果没有,我想知道是否有任何有效的替代方案可以在JavaScript中使用。我已经考虑过一点了,但是没有任何优雅的解决方案能够在大多数情况下(如果不是全部的话)都有效 具体地说,我只需要使用.split()和.replace()方法的替代方法,但是如果它可以更一般化,那将是最好的 例如: 输入字符串:+bar+baz“not

从中,我推断匹配给定正则表达式的所有实例(不在引号内)是不可能的。也就是说,它不能匹配转义引号(例如:
“应该采用整个匹配”
)。如果有一种我不知道的方法可以解决我的问题

然而,如果没有,我想知道是否有任何有效的替代方案可以在JavaScript中使用。我已经考虑过一点了,但是没有任何优雅的解决方案能够在大多数情况下(如果不是全部的话)都有效

具体地说,我只需要使用.split()和.replace()方法的替代方法,但是如果它可以更一般化,那将是最好的

例如:
输入字符串:
+bar+baz“not+”或\“+或+\”this+”foo+bar+


将+替换为#,而不是内部引号,将返回:

  • 使用正则表达式全局替换将所有字符串正文内容提取到边表中
  • 你用逗号翻译吗
  • 使用正则表达式全局替换将字符串体调回
  • 代码如下

    // Step 1
    var sideTable = [];
    myString = myString.replace(
        /"(?:[^"\\]|\\.)*"/g,
        function (_) {
          var index = sideTable.length;
          sideTable[index] = _;
          return '"' + index + '"';
        });
    // Step 2, replace commas with newlines
    myString = myString.replace(/,/g, "\n");
    // Step 3, swap the string bodies back
    myString = myString.replace(/"(\d+)"/g,
        function (_, index) {
          return sideTable[index];
        });
    
    如果在设置后运行

    myString = '{:a "ab,cd, efg", :b "ab,def, egf,", :c "Conjecture"}';
    
    你应该

    {:a "ab,cd, efg"
     :b "ab,def, egf,"
     :c "Conjecture"}
    
    它起作用了,因为在第一步之后

    myString = '{:a "0", :b "1", :c "2"}'
    sideTable = ["ab,cd, efg", "ab,def, egf,", "Conjecture"];
    
    因此myString中唯一的逗号是字符串外部。步骤2,然后将逗号转换为换行符:

    myString = '{:a "0"\n :b "1"\n :c "2"}'
    

    最后,我们将只包含数字的字符串替换为其原始内容。

    实际上,您可以为任何字符串匹配不包含引号的正则表达式的所有实例,其中每个开头引号都会再次关闭。比如说,正如上面的示例中所示,您希望匹配
    \+

    这里的关键观察是,如果一个单词后面有偶数个引号,那么它就在引号之外。这可以建模为前瞻性断言:

    \+(?=([^"]*"[^"]*")*[^"]*$)
    
    现在,您希望不计算转义引号。这会变得更复杂一些。而不是<>代码> [^ ] */COD>,它进入下一个引用,您还需要考虑反斜杠,并使用<代码> [^ \\\**/COD>。到达反斜杠或引号后,如果遇到反斜杠,则需要忽略下一个字符,或者前进到下一个未替换的引号。这看起来像是
    (\\.\”([^“\\]*\\\)*[^“\\]*”
    。加起来,你就到了

    \+(?=([^"\\]*(\\.|"([^"\\]*\\.)*[^"\\]*"))*[^"]*$)
    

    我承认这有点神秘

    Azmisov,重新提出这个问题,因为您说您正在寻找
    任何可以在JavaScript中使用的有效替代方案
    ,以及
    任何可以在大多数(如果不是全部)情况下使用的优雅解决方案

    碰巧有一个简单的、通用的解决方案没有提到

    与备选方案相比,此解决方案的正则表达式非常简单:

    "[^"]+"|(\+)
    
    我们的想法是匹配,但忽略引号中的任何内容,以中和该内容(在替换的左侧)。在右侧,我们捕获所有未中和到组1中的
    +
    ,替换函数检查组1。以下是完整的工作代码:

    <script>
    var subject = '+bar+baz"not+these+"foo+bar+';
    var regex = /"[^"]+"|(\+)/g;
    replaced = subject.replace(regex, function(m, group1) {
        if (!group1) return m;
        else return "#";
    });
    document.write(replaced);
    

    转义引号呢?

    同样,以上是展示该技术的一般答案。“ignorethismatch”正则表达式不仅可以根据您的需要进行优化,还可以添加多个要忽略的表达式。例如,如果要确保已充分忽略转义引号,可以先在其他两个引号前面添加一个替代项
    \\\“
    ,以便匹配(并忽略)散乱的转义双引号

    接下来,在捕获双引号字符串内容的部分
    “[^”]*”
    中,您可以添加一个替代项,以确保转义的双引号在它们的
    有机会变为结束哨兵,将其变为
    ”(?:\\“|[^]”)*“

    结果表达式有三个分支:

  • \\”
    匹配并忽略
  • “(?:\\“\[^”])*”
    匹配并忽略
  • (\+)
    要匹配,捕获和处理
  • 请注意,在其他regex版本中,我们可以使用lookback更轻松地完成这项工作,但JS不支持它

    完整正则表达式变为:

    \\"|"(?:\\"|[^"])*"|(\+)
    
    见和

    参考


  • 尽管zx81给出的答案似乎是性能最好且清晰的答案,但它需要以下修复来正确捕获转义引号:

    var subject = '+bar+baz"not+or\\"+or+\\"this+"foo+bar+';
    

    还有前面提到的“group1==未定义”或“!group1”。 特别是2。实际上,考虑原始问题中提出的所有问题似乎都很重要


    但是应该提到的是,此方法隐式要求字符串在未转义引号对之外不包含转义引号。

    谢谢!我认为这是不可能的。我100%的理解这个理论,大约60%的正则表达式,当我自己写的时候,我的理解率降到了0%。哦,也许有一天吧。嘿,有没有办法让正则表达式与JavaScript的.split()方法一起工作?它似乎忽略了全局标志…不管怎样,只是忘了在所有的括号中加上
    ?:
    \+(?=(?:[^“\\]*(?:\.\.\124;”(?:[^“\]*\.*”*[^“\]*”)[^“]*$)
    尝试在项目中使用此选项,但失败。我发现原因是两个单引号内有一个双引号
    …这将导致字符串中双引号的数量为奇数请大家看看@zx81在其答案中建议的解决方案。如果可以使用+1作为优雅的非正则表达式解决方案,那么它更易于编写,并且具有更好的性能。不过,对于我所做的事情来说,正则表达式要灵活一些。这种方法实际上比@Jens建议的前瞻性方法要好。它更容易编写,性能也更好。我没有注意到并使用了前瞻性方法,直到我遇到了一个性能问题,为了匹配150万条文本,在这种方法启动时,前瞻性方法使用了大约90秒
    var subject = '+bar+baz"not+or\\"+or+\\"this+"foo+bar+';
    
    var regex = /"(?:[^"\\]|\\.)*"|(\+)/g;