后向和前向同时查找

时间:2019-06-02 05:43:43

标签: javascript regex clojurescript regex-lookarounds lookbehind

我正在寻找一个正则表达式,以在:字符上拆分用户提供的字符串,但是当用户转义了冒号\:或它是url的一部分(例如, https://stackoverflow..。 在javascript中,大多数浏览器尚不支持lookbehinds。可以为后向部分应用其他方法吗?

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

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

,但不在Safari中(例如)。

3 个答案:

答案 0 :(得分:2)

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

一种解决方法(不是很漂亮,但是可以起作用)是首先用一些您知道不会在文本中自然出现的“符号”来代替\:,然后进行拆分,然后将任何{{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); ,也可以使用@Skeeve的匹配解决方案,因为这样做更优雅。

答案 1 :(得分:1)

另一种选择是不搜索分隔符,而是搜索元素:

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. 您忘记了URL可以包含多个冒号。那么“ http://me:password@myhost.com:8080/path?value=d:f

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

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

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

P.P.S。修复了发现的@chatnoir错字

答案 2 :(得分:1)

您还可以使用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));