我正在寻找一个正则表达式,以在:
字符上拆分用户提供的字符串,但是当用户转义了冒号\:
或它是url的一部分(例如, https://stackoverflow..
。
在javascript中,大多数浏览器尚不支持lookbehinds。可以为后向部分应用其他方法吗?
在Chrome上的clojure / Clojurescript(确实支持lookbehinds)中,此正则表达式可以解决问题:
#"(?<!\):(?!//)"
,但不在Safari中(例如)。
答案 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" ]
除了这些,我认为它应该对您有用。
我认为您只能通过使用regexp-exec或多或少的复杂循环来克服这些缺点。
P.S。我知道这里不需要分组,但是如果您想在regexp-exec中使用它,就需要它。 缺点:
P.P.S。修复了发现的@chatnoir错字
答案 2 :(得分:1)
您还可以使用replace并将一个函数作为第二个参数传递。
您可以使用模式来匹配不需要的内容,并在组中捕获要保留的内容。然后,您可以用标记替换要保留的部分,就像@chatnoir的方法一样,然后在该标记上拆分。
:\/\/\S+|\\:|(:)
说明
:\/\/\S+
匹配://
,后跟1+次非空格字符|
或\\:
匹配\:
|
或(:)
在组1中捕获:
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));