我如何匹配多个匹配的正则expression式类似于PHP的preg_match_all()?
我正试图parsing由&
或&
分隔的key = value对组成的url编码的string&
。
以下仅匹配第一个匹配项,将键和值拆分为单独的结果元素:
var result = mystring.match(/(?:&|&)?([^=]+)=([^&]+)/)
string'1111342 = Adam%20Franco&348572 = Bob%20Jones'的结果是:
['1111342', 'Adam%20Franco']
使用全局标志“g”将会匹配所有的匹配项,但是只返回完全匹配的子串,而不是分离的键和值:
var result = mystring.match(/(?:&|&)?([^=]+)=([^&]+)/g)
string'1111342 = Adam%20Franco&348572 = Bob%20Jones'的结果是:
['1111342=Adam%20Franco', '&348572=Bob%20Jones']
虽然我可以分割string和分开每个键/值对,是否有任何方式使用JavaScript的正则expression式支持匹配模式/(?:&|&)?([^=]+)=([^&]+)/
类似于PHP的preg_match_all()
函数?
我打算以某种方式获得结果的子比赛分离如下:
[['1111342', '348572'], ['Adam%20Franco', 'Bob%20Jones']]
要么
[['1111342', 'Adam%20Franco'], ['348572', 'Bob%20Jones']]
我会build议一个替代正则expression式,使用子组来分别捕获参数的名称和值:
function getUrlParams(url) { var re = /(?:\?|&(?:amp;)?)([^=&#]+)(?:=?([^&#]*))/g, match, params = {}, decode = function (s) {return decodeURIComponent(s.replace(/\+/g, " "));}; if (typeof url == "undefined") url = document.location.href; while (match = re.exec(url)) { params[decode(match[1])] = decode(match[2]); } return params; } var result = getUrlParams("http://maps.google.de/maps?f=q&source=s_q&hl=de&geocode=&q=Frankfurt+am+Main&sll=50.106047,8.679886&sspn=0.370369,0.833588&ie=UTF8&ll=50.116616,8.680573&spn=0.35972,0.833588&z=11&iwloc=addr");
result
是一个对象:
{ f:“q” 地理编码:“” hl:“de” 即:“UTF8” iwloc:“addr” ll:“50.116616,8.680573” q:“法兰克福” sll:“50.106047,8.679886” 来源:“s_q” spn:“0.35972,0.833588” sspn:“0.370369,0.833588” z:“11” }
正则expression式分解如下:
(?:#未捕获组 \?|&#“?” 要么 ”&” (?:放大器;)? #(允许“&”,错误的HTML编码的URL) )#结束非捕获组 (#组1 [^ =&#] +#除“=”,“&”或“#”之外的任何字符; 至less一次 )#结束组1 - 这将是参数的名称 (?:#未捕获组 =? #一个“=”,可选 (#组2 [^&#] *#除“&”或“#”之外的任何字符; 任何次数 )#结束组2 - 这将是参数的值 )#结束非捕获组
您需要使用“g”开关进行全局search
var result = mystring.match(/(&|&)?([^=]+)=([^&]+)/g)
如果您不想依赖运行exec
样式匹配的“盲目匹配”,那么JavaScript就会内置匹配全部function,但是它是replace
函数调用的一部分,当使用“如何处理捕获组“ 处理function :
var data = {}; var getKeyValue = function(a,b,c,d) { data[c] = d; }; mystring.replace(/(?:&|&)?([^=]+)=([^&]+)/g, getKeyValue);
完成。 而不是使用捕获组处理函数来实际返回replacestring(为了replace处理,第一个arg,这里称为here,是全模式匹配,后续args是单独的捕获组,在这种情况下, b
是group 1, c
group 2等),我们只需采取组2和3捕获,并caching那对。
所以,不要写复杂的parsing函数,记住JavaScript中的“matchAll”函数只是用replace句柄函数“replace”,并且可以有很多模式匹配的效率。
为了捕获组,我习惯于在PHP中使用preg_match_all
,并试图在这里复制它的function:
<script> // Return all pattern matches with captured groups RegExp.prototype.execAll = function(string) { var match = null; var matches = new Array(); while (match = this.exec(string)) { var matchArray = []; for (i in match) { if (parseInt(i) == i) { matchArray.push(match[i]); } } matches.push(matchArray); } return matches; } // Example var someTxt = 'abc123 def456 ghi890'; var results = /[az]+(\d+)/g.execAll(someTxt); // Output [["abc123", "123"], ["def456", "456"], ["ghi890", "890"]] </script>
设置全局匹配的g
修饰符:
/…/g
来源: https : //developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
寻找连续的比赛
如果您的正则expression式使用“g”标志,则可以多次使用exec()方法在同一个string中查找连续的匹配项。 当你这样做的时候,search从正则expression式的lastIndex属性指定的str的子string开始(test()也将前进lastIndex属性)。 例如,假设你有这个脚本:
var myRe = /ab*/g; var str = 'abbcdefabh'; var myArray; while ((myArray = myRe.exec(str)) !== null) { var msg = 'Found ' + myArray[0] + '. '; msg += 'Next match starts at ' + myRe.lastIndex; console.log(msg); }
该脚本显示以下文本:
Found abb. Next match starts at 3 Found ab. Next match starts at 912
注意:不要将正则expression式(或RegExp构造函数)置于while条件中,否则将在每次迭代时重置lastIndex属性导致匹配时创build无限循环。 还要确保全局标志被设置,否则在这里也会出现循环。
如果有人(比如我)需要Tomalak的方法支持数组(如多选),这里是:
function getUrlParams(url) { var re = /(?:\?|&(?:amp;)?)([^=&#]+)(?:=?([^&#]*))/g, match, params = {}, decode = function (s) {return decodeURIComponent(s.replace(/\+/g, " "));}; if (typeof url == "undefined") url = document.location.href; while (match = re.exec(url)) { if( params[decode(match[1])] ) { if( typeof params[decode(match[1])] != 'object' ) { params[decode(match[1])] = new Array( params[decode(match[1])], decode(match[2]) ); } else { params[decode(match[1])].push(decode(match[2])); } } else params[decode(match[1])] = decode(match[2]); } return params; } var urlParams = getUrlParams(location.search);
input?my=1&my=2&my=things
结果1,2,things
(以前只返回:东西)
只要坚持提出的问题如标题所示,您实际上可以使用String.prototype.replace()
迭代string中的每个匹配。 例如下面的代码就是基于正则expression式获取所有单词的数组:
function getWords(str) { var arr = []; str.replace(/\w+/g, function(m) { arr.push(m); }); return arr; } var words = getWords("Where in the world is Carmen Sandiego?"); // > ["Where", "in", "the", "world", "is", "Carmen", "Sandiego"]
如果我想获得捕获组,甚至每场比赛的索引,我也可以这样做。 以下显示每个比赛如何与整个比赛,第一个捕获组和索引一起返回:
function getWords(str) { var arr = []; str.replace(/\w+(?=(.*))/g, function(m, remaining, index) { arr.push({ match: m, remainder: remaining, index: index }); }); return arr; } var words = getWords("Where in the world is Carmen Sandiego?");
运行完上面的内容后, words
将会如下所示:
[ { "match": "Where", "remainder": " in the world is Carmen Sandiego?", "index": 0 }, { "match": "in", "remainder": " the world is Carmen Sandiego?", "index": 6 }, { "match": "the", "remainder": " world is Carmen Sandiego?", "index": 9 }, { "match": "world", "remainder": " is Carmen Sandiego?", "index": 13 }, { "match": "is", "remainder": " Carmen Sandiego?", "index": 19 }, { "match": "Carmen", "remainder": " Sandiego?", "index": 22 }, { "match": "Sandiego", "remainder": "?", "index": 29 } ]
为了匹配多个与preg_match_all
可用的相似的事件,您可以使用这种types的思维来创build自己的或使用类似YourJS.matchAll()
东西。 YourJS或多或less地定义这个函数如下:
function matchAll(str, rgx) { var arr, extras, matches = []; str.replace(rgx.global ? rgx : new RegExp(rgx.source, (rgx + '').replace(/[\s\S]+\//g , 'g')), function() { matches.push(arr = [].slice.call(arguments)); extras = arr.splice(-2); arr.index = extras[0]; arr.input = extras[1]; }); return matches[0] ? matches : null; }
如果您可以使用map
这是一个四线解决scheme:
var mystring = '1111342=Adam%20Franco&348572=Bob%20Jones'; var result = mystring.match(/(&|&)?([^=]+)=([^&]+)/g) || []; result = result.map(function(i) { return i.match(/(&|&)?([^=]+)=([^&]+)/); }); console.log(result);
为了使用相同的名称捕获几个参数,我修改了Tomalak方法中的while循环,如下所示:
while (match = re.exec(url)) { var pName = decode(match[1]); var pValue = decode(match[2]); params[pName] ? params[pName].push(pValue) : params[pName] = [pValue]; }
input: ?firstname=george&lastname=bush&firstname=bill&lastname=clinton
返回: {firstname : ["george", "bill"], lastname : ["bush", "clinton"]}
那么…我有一个类似的问题…我想用RegExp的增量/步骤search(例如:开始search…做一些处理…继续search,直到最后一场比赛)
经过大量的互联网search…像往常一样(这是一个习惯现在)我最终在StackOverflow并find答案…
什么是不被提及和要提及的是“ lastIndex
”我现在明白为什么RegExp对象实现“ lastIndex
”属性
使用window.URL
:
> s = 'http://www.example.com/index.html?1111342=Adam%20Franco&348572=Bob%20Jones' > u = new URL(s) > Array.from(u.searchParams.entries()) [["1111342", "Adam Franco"], ["348572", "Bob Jones"]]
拆分它看起来对我来说是最好的select:
'1111342=Adam%20Franco&348572=Bob%20Jones'.split('&').map(x => x.match(/(?:&|&)?([^=]+)=([^&]+)/))