【问题标题】:Lookbehind alternative with both lookbehind and lookahead具有lookbehind和lookahead的lookbehind替代方案
【发布时间】:2019-10-18 03:07:10
【问题描述】:

我正在寻找一个正则表达式来拆分用户在 : 字符上提供的字符串,但不是当用户已经转义冒号 \: 或者它是 URL 的一部分时,例如https://stackoverflow..。 在 javascript 中,大多数浏览器还不支持lookbehinds。是否可以对后视部分应用其他方法?

在 Chrome 上的 clojure/ Clojurescript 中(确实支持后视),这个正则表达式可以解决问题:

#"(?<!\):(?!//)"

但不是在 Safari 中(例如)。

【问题讨论】:

标签: javascript regex clojurescript regex-lookarounds lookbehind


【解决方案1】:

主要问题是当前浏览器不支持后向查找,这是查找和否定前缀\所必需的,因此我们不包括\:

一种解决方法(不是很漂亮,但很有效)是首先将\: 替换为您知道文本中不会自然出现的一些“符号”,然后进行拆分,然后替换回任何\:

例如,如果您的字符串中有“::”,则此方法将返回一个空元素“”:

let regex = /:(?!\/\/)/

//original string literal \: has to be expressed as \\:
let str = "http://example.com::hello:dolly:12\\:00\\:PM";

//substitute out any \: 
str = str.replace(/\\:/g,"<colon>"); //http://example.com::hello:dolly:12<colon>00<colon>PM

//now we split 'normally' without lookbehind
let arr = str.split(regex); //[ 'http://example.com', '', 'hello', 'dolly', '12\\:00\\:PM' ]

//substitute back \:
arr = arr.map(element => element.replace(/<colon>/g, "\\:")); //[ 'http://example.com', '', 'hello', 'dolly', '12\\:00\\:PM' ]

console.log(arr);

如果您只是在寻找非空元素,您可以在其上执行arr.filter(Boolean),或者只使用@Skeeve 的匹配解决方案,因为它更适合此目的。

【讨论】:

    【解决方案2】:

    另一种方法是不搜索分隔符,而是搜索元素:

    var str="this:is\\:a:test:https://stackoverflow:80:test::test";
    var elements= str.match(/((?:[^\\:]|\\:|:\/\/)+)/g);
    // elements= [ "this", "is\\:a", "test", "https://stackoverflow", "80", "test", "test" ]
    
    1. 元素可能不为空(观察正则表达式中的“+”)以及最后 2 个“测试”之间的空元素如何丢失
    2. 您忘记了一个 URL 可以包含多个冒号。 `http://me:password@myhost.com:8080/path?value=d:f'呢

    除了这些,我认为它应该对你有用。

    我认为你只能通过使用 regexp-exec 的或多或少复杂的循环来克服缺点。

    附:我知道这里不需要分组,但是如果你想在 regexp-exec 中使用它,你就需要它。 缺点:

    附言修复了@chatnoir 发现的错字

    【讨论】:

    • 不应该将“ist\:a”作为元素返回,而不是拆分为“ist”和“a”吗?
    • 我认为你的 str 应该是="this:ist\\:a..." (即\\: 表示\:
    【解决方案3】:

    您也可以使用replace 并传递一个函数作为第二个参数。

    您可以使用一种模式来匹配您不想要的内容,并在一个组中捕获您想要保留的内容。然后你可以用一个标记替换你想要保留的部分,就像@chatnoir 的方法一样,然后在那个标记上分割。

    :\/\/\S+|\\:|(:)
    

    说明

    • :\/\/\S+ 匹配 :// 后跟 1+ 次非空白字符
    • |或者
    • \\: 匹配\:
    • |或者
    • (:) 在组 1 中捕获 :

    Regex demo

    let pattern = /:\/\/\S+|\\:|(:)/g;
    let str = "string\\: or https://www.example.com:8000 or split:me or te\\:st or \\:test or notsplit\\:me:splitted or \\: or ftp://example.com :";
    
    str = str.replace(pattern, function(match, group1) {
      return group1 === undefined ? match : "<split>"
    });
    
    console.log(str.split("<split>").filter(Boolean));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多