如何使用类似于PHP';的JavaScript中的正则表达式匹配多个事件;s preg_match_all()?
我试图解析url编码的字符串,这些字符串由键=值对组成,由如何使用类似于PHP';的JavaScript中的正则表达式匹配多个事件;s preg_match_all()?,javascript,regex,Javascript,Regex,我试图解析url编码的字符串,这些字符串由键=值对组成,由&或&;分隔 以下内容仅与第一个匹配,将键和值拆分为单独的结果元素: var result = mystring.match(/(?:&|&)?([^=]+)=([^&]+)/) 字符串“1111342=Adam%20Franco&348572=Bob%20Jones”的结果为: ['1111342', 'Adam%20Franco'] ['1111342=Adam%20Franco', '&am
&
或&;分隔代码>
以下内容仅与第一个匹配,将键和值拆分为单独的结果元素:
var result = mystring.match(/(?:&|&)?([^=]+)=([^&]+)/)
字符串“1111342=Adam%20Franco&348572=Bob%20Jones”的结果为:
['1111342', 'Adam%20Franco']
['1111342=Adam%20Franco', '&348572=Bob%20Jones']
使用全局标志“g”将匹配所有匹配项,但仅返回完全匹配的子字符串,而不是单独的键和值:
var result = mystring.match(/(?:&|&)?([^=]+)=([^&]+)/g)
字符串“1111342=Adam%20Franco&348572=Bob%20Jones”的结果为:
['1111342', 'Adam%20Franco']
['1111342=Adam%20Franco', '&348572=Bob%20Jones']
虽然我可以在&
上拆分字符串并分别拆分每个键/值对,但有没有办法使用JavaScript的正则表达式支持来匹配模式/(?:&&&;)?([^=]+)=([^&]+)/
的多次出现,类似于PHP的preg_match_all()
函数
我的目标是通过将子匹配分开来获得结果,如:
[['1111342', '348572'], ['Adam%20Franco', 'Bob%20Jones']]
或
为全局匹配设置g
修饰符:
/…/g
您需要使用“g”开关进行全局搜索
var result = mystring.match(/(&|&)?([^=]+)=([^&]+)/g)
已从评论中删除
2020年评论:我们不再使用正则表达式,而是使用正则表达式,它为我们完成了所有这些,因此不再需要自定义代码,更不用说正则表达式了
–
此处列出了浏览器支持
我建议使用另一种正则表达式,使用子组分别捕获参数的名称和值,并:
result
是一个对象:
{
f: "q"
geocode: ""
hl: "de"
ie: "UTF8"
iwloc: "addr"
ll: "50.116616,8.680573"
q: "Frankfurt am Main"
sll: "50.106047,8.679886"
source: "s_q"
spn: "0.35972,0.833588"
sspn: "0.370369,0.833588"
z: "11"
}
{
f:“q”
地理编码:“
hl:“德”
ie:“UTF8”
iwloc:“地址”
LH:“50.116616,8.680573”
问:“法兰克福美茵河畔”
sll:“50.106047,8.679886”
资料来源:“s_q”
spn:“0.35972,0.833588”
sspn:“0.370369,0.833588”
z:“11”
}
正则表达式细分如下:
(?: # non-capturing group
\?|& # "?" or "&"
(?:amp;)? # (allow "&", for wrongly HTML-encoded URLs)
) # end non-capturing group
( # group 1
[^=]+ # any character except "=", "&" or "#"; at least once
) # end group 1 - this will be the parameter's name
(?: # non-capturing group
=? # an "=", optional
( # group 2
[^]* # any character except "&" or "#"; any number of times
) # end group 2 - this will be the parameter's value
) # end non-capturing group
[
{
"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
}
]
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;
}
(?:#非捕获组
\|“?”或“&”
(?:amp;)?#(允许“&;”,用于错误的HTML编码URL)
)#结束非捕获组
(#第一组)
[^=]+#除“=”、“&”或“#”之外的任何字符至少一次
)#结束组1-这将是参数的名称
(?:#非捕获组
=?#一个“=”,可选
(#第2组)
[^]*#除“&”或“#”以外的任何字符,任意次数
)#结束组2-这将是参数的值
)#结束非捕获组
为了捕获组,我习惯于在PHP中使用preg\u match\u all
,我尝试在这里复制它的功能:
<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 = /[a-z]+(\d+)/g.execAll(someTxt);
// Output
[["abc123", "123"],
["def456", "456"],
["ghi890", "890"]]
</script>
//返回捕获组的所有模式匹配
RegExp.prototype.execAll=函数(字符串){
var match=null;
var matches=新数组();
while(match=this.exec(字符串)){
var matchArray=[];
因为(我在比赛中){
if(parseInt(i)=i){
matchArray.push(匹配[i]);
}
}
matches.push(匹配数组);
}
返回比赛;
}
//范例
var someTxt='abc123 def456 ghi890';
var results=/[a-z]+(\d+)/g.execAll(someTxt);
//输出
[“abc123”,“123”],
[“def456”,“456”],
[“ghi890”,“890”]]
嗯。。。我也有类似的问题。。。
我需要使用RegExp进行增量/分步搜索
(例如:开始搜索…进行一些处理…继续搜索直到最后一次匹配)
经过大量的网络搜索。。。像往常一样(现在这已成为一种习惯)
我最终在StackOverflow找到了答案
没有提及的内容和需要提及的事项是“lastIndex
”
现在我明白了为什么RegExp对象实现了“lastIndex
”属性”以使用相同的名称捕获多个参数,我修改了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];
}
输入:?firstname=george&lastname=bush&firstname=bill&lastname=clinton
返回:{firstname:[“george”,“bill”],lastname:[“bush”,“clinton”]}
如果有人(像我一样)需要使用支持数组的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);
输入?my=1&my=2&my=things
结果1,2,things
(早期仅返回:things)2020编辑
使用,因为此作业不再需要任何类型的自定义代码。浏览器可以通过单个构造函数为您实现这一点:
const str = "1111342=Adam%20Franco&348572=Bob%20Jones";
const data = new URLSearchParams(str);
for (pair of data) console.log(pair)
屈服
Array [ "1111342", "Adam Franco" ]
Array [ "348572", "Bob Jones" ]
因此,没有理由再使用正则表达式进行此操作
原始答案
如果您不想依赖于运行样式匹配附带的“盲匹配”,JavaScript确实内置了匹配所有功能,但在使用“如何处理捕获组”时,它是函数调用的一部分:
完成了
我们不使用capture group handling函数实际返回替换字符串(对于替换处理,第一个参数是完整模式匹配,后续参数是单独的捕获组),而是简单地获取组2和3捕获,并缓存该对
因此,不要编写复杂的解析函数,记住JavaScript中的“matchAll”函数只是用替换处理程序函数“replace”,可以获得更高的模式匹配效率。只需坚持标题中提出的问题,实际上,您可以使用string.prototype.replace()
在字符串中迭代每个匹配项。例如,以下操作仅用于获取基于正则表达式的所有单词的数组:
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?");
运行上述操作后,单词将如下所示:
(?: # non-capturing group
\?|& # "?" or "&"
(?:amp;)? # (allow "&", for wrongly HTML-encoded URLs)
) # end non-capturing group
( # group 1
[^=]+ # any character except "=", "&" or "#"; at least once
) # end group 1 - this will be the parameter's name
(?: # non-capturing group
=? # an "=", optional
( # group 2
[^]* # any character except "&" or "#"; any number of times
) # end group 2 - this will be the parameter's value
) # end non-capturing group
[
{
"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
}
]
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;
}
为了匹配与PHP中可用的类似的多个事件,您可以使用这种类型的思维来创建自己的或使用类似的东西。YourJS或多或少定义了
> 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"]]
'1111342=Adam%20Franco&348572=Bob%20Jones'.split('&').map(x => x.match(/(?:&|&)?([^=]+)=([^&]+)/))
long count = 0;
var remainder = data;
Match match = null;
do
{
match = _rgx.Match(remainder);
if (match.Success)
{
count++;
remainder = remainder.Substring(match.Index + 1, remainder.Length - (match.Index+1));
}
} while (match.Success);
return count;
1111342 => Adam%20Franco
348572 => Bob%20Jones