将一个查询字符串参数解析为Javascript数组

5

我有一个查询字符串 www.example.com/yy?q=how+can+i+get+this&o=1&source=home

如何使用 javascript 或 jquery 解析出仅包含 q 参数值的数组?

我想要得到以下数组:

['how', 'can', 'i', 'get', 'this']
3个回答

2
假设您的查询字符串的顺序并不总是已知的,并且您需要支持在任何地方查找“q”;
// substring(1) to skip the '?' character
var queryStrings = window.location.search.substring(1).split('&');
var qArray;
for (var i = 0; i < queryStrings.length; i++) {
  if (queryStrings[i].substring(0, 2) === 'q=') {
    qArray = queryStrings[i].substring(2).split('+');
    break;
  }
}

它返回['q=how', 'can', 'i', 'get', 'this'] - Hayi
我用 var qArray = q[0].replace('q=','').split('+'); 替换了最后一行代码,它成功运行了。 - Hayi
我已经更新了它,增加了一个子字符串调用来跳过那些字符,替换也可以,但不会在该字符串的第一个实例停止,所以不够干净。 - diadical
谢谢,但我选择使用循环来完成。您能否更新您的答案以在第一次出现时停止,像这样:for (var i in queryStrings) { if( queryStrings[i].substring(0, 2) === 'q=' ){ array = queryStrings[i].replace('q=','').split('+'); break; } } - Hayi
1
我已经更新了它以执行for循环,但您会注意到我使用的是for而不是for...in。对于一些原因,for in在常规数组上可能比较危险,虽然在现代浏览器中有些问题已经不存在了,但如果您正在使用扩展基本数组对象的库(即shims或某些框架),那么就会出现错误。这些属性将被迭代,就好像它们是索引一样。请尝试使用for...in进行对象迭代,请参见此处 - diadical
如果 URL 中包含%20而不是+,或者 URL 中包含任何百分号编码的字符,这个解决方案将失败。 - zzzzBov

2
您的问题实际上是一系列需要回答的问题的组合,每个问题都需要回答才能进入下一步。
您问如何从查询字符串中提取q参数并将其拆分为多个单词,但这忽略了您首先需要解析URL的事实。
第1部分:将URL解析为各个部分
您标记了,这是完全不必要的。但是,这告诉我您正在浏览器环境中工作,而不是在服务器端JavaScript中工作,这意味着我们可以使用一些技巧来解析URL,这些技巧在中不可用。
如果您知道要从当前 URL获取查询字符串,只需访问location.search即可。
如果您有一个URL字符串,并且想要获取查询字符串,可以使用元素自动进行解析。请参考链接解剖学,了解URL的各个部分是什么:
function parseUrl(url) {
  var a = document.createElement('a');
  a.href = url;
  return {
    href: a.href,
    protocol: a.protocol,
    host: a.host,
    hostname: a.hostname,
    port: a.port,
    pathname: a.pathname,
    search: a.search,
    hash: a.hash
  };
}

值得注意的是,给出的URL(www.example.com/yy?q=how+can+i+get+this&o=1&source=home)格式不正确,缺少协议,这意味着解析它将会导致pathname被视为相对路径。要修复此问题,请在URL前加上http://
var parts = parseUrl('http://www.example.com/yy?q=how+can+i+get+this&o=1&source=home');
var search = parts.search;

function parseUrl(url) {
  var a = document.createElement('a');
  a.href = url;
  return {
    href: a.href,
    protocol: a.protocol,
    host: a.host,
    hostname: a.hostname,
    port: a.port,
    pathname: a.pathname,
    search: a.search,
    hash: a.hash
  };
}
var parts = parseUrl('http://www.example.com/yy?q=how+can+i+get+this&o=1&source=home');
console.log(parts);

第二部分:将查询字符串解析成部分

这部分很容易搞砸,因为查询字符串很难处理(完全透明,我写了那篇博客)。

任何试图使用正则表达式解析查询字符串的人可能在很多方面都是错误的。

我的建议是不要重复造轮子我写了一个QueryString解析器,它带有MIT许可证,或者如果您不放心我尝试的解决方案,请考虑使用querystring模块,该模块可与一起使用。

我自己编写的模块使用UMD,因此它应该与大多数项目兼容,无论您使用什么(或不使用)打包和依赖管理。

var qs = new QueryString({
  flatten: true,
  semicolons: false
});
console.log(qs.parse('?q=how+can+i+get+this&o=1&source=home'));
<script src="https://cdn.rawgit.com/zzzzBov/QueryStringJS/master/dist/querystring.min.js"></script>

第三部分:按空格拆分字符串

这一部分看起来很简单。可以告诉您使用以下代码:

'how can i get this'.split(' ');

但这可能并不是您真正想要的。如果您还想在制表符或换行符上进行拆分,那么它就更加复杂了。您可能还想避免数组中的空字符串(例如' foo bar '会有3个空字符串)。如果不知道您的意图,很难推荐一种行动方案。通常,使用类似于/\s+/g的正则表达式进行拆分,然后过滤任何可能的前导和尾随空字符串是一种更具弹性的解决方案:

var arr = 'how can i get this'.split(/\s+/g).filter(function (v) {
  return v;
});

第四部分:齐心协力

var parts,
    qs,
    queryString,
    arr;

function parseUrl(url) {
  var a = document.createElement('a');
  a.href = url;
  return {
    href: a.href,
    protocol: a.protocol,
    host: a.host,
    hostname: a.hostname,
    port: a.port,
    pathname: a.pathname,
    search: a.search,
    hash: a.hash
  };
}

parts = parseUrl('http://www.example.com/yy?q=how+can+i+get+this&o=1&source=home');
console.log('parts', parts);

qs = new QueryString({
  flatten: true,
  semicolons: false
});
queryString = qs.parse(parts.search);
console.log('query string', queryString);

arr =
  (queryString.q || '')
    .split(/\s+/g)
    .filter(function (v) {
      return v;
    });
console.log('array', arr);
<script src="https://cdn.rawgit.com/zzzzBov/QueryStringJS/master/dist/querystring.min.js"></script>


现在这可能看起来像是一堆工作,而且确实如此。不幸的是,JS并没有对一些常用功能提供很多本地支持。 UrlSearchParams 有部分浏览器支持,但即使如此,在解析查询字符串方面仍然存在问题。
只需确保正确处理每个部分,否则用户可以简单地更改您页面的URL,并可能以意想不到的方式导致崩溃。

注意,stacksnippets正在记录错误 { "message": "Uncaught TypeError: Cannot read property 'split' of undefined", "filename": "http://stacksnippets.net/js", "lineno": 46, "colno": 5 } - guest271314
Chromium。相信这是由于.search引起的?当尝试此问题中的示例URL时,结果为空字符串。https://jsfiddle.net/hokqjgpj/ - guest271314
没有删除您代码片段的任何部分。只是使用了来自链接问题的输入字符串。由于我们之前的沟通,认为您的答案足够全面,可以处理任何输入字符串,因此将其链接到了上面的问题。尝试了来自其他问题的字符串,但遇到了错误。 “但在示例中写得很好” 。嗯,对于这个特定的问题,下面的答案也是如此。 - guest271314
@guest271314,听起来你不理解q=foo%20bar#baz在我的例子中应该放在哪里。除非以?为前缀,否则它不是查询字符串,而是相对路径。如果你只想解析'q=foo%20bar#baz',那么你可以使用qs.parse('q=foo%20bar#baz'),你会看到它返回了正确的结果。 - zzzzBov
“听起来你似乎不理解在我的例子中q=foo%20bar#baz应该放在哪里。”并不是说你的例子或观点被误解了。从这个角度来看,你的例子超出了实际原始问题的范围。也许你认为问题比它包含的文本更广泛,或者问题的答案应该处理包括编码短语在内的每个可能的查询字符串。实际原始问题并没有提出这个问题。我对你的回答没有意见。鉴于实际原始问题,"downvote"你自己的回答是不必要的。 - guest271314
显示剩余4条评论

0

尝试在输入字符串 str 上利用 String.prototype.match(),带有 RegExp 参数 / q = \ w +。* / 来匹配以“q =”开头的字符串;使用从 .match()返回的数组中索引为 0 的字符串项调用 .split(),带有 RegExp 参数 / q = |&amp;。* | \ + |#|%20 / ;使用 .filter() .split()返回的数组中删除空项

var res = str.match(/q=\w+.*/)[0].split(/q=|&.*|\+|#|%20/).filter(Boolean);

var str = "www.example.com/yy?q=how+can+i+get+this&o=1&source=home";
var res = str.match(/q=\w+.*/)[0].split(/q=|&.*|\+/).filter(Boolean); 
document.write(JSON.stringify(res));


@Kenster 不知道那个。这是“踩”的原因吗? - guest271314
1
@guest271314,给我点个踩吧,我现在才有时间回来适当地回答这个问题。你的答案未能正确解码查询字符串值,如果URL中有一个哈希值,它将被包含在该参数的正则表达式匹配中。 - zzzzBov
@zzzzBov,你能分享一個問題的例子,說明你所描述的方法在處理這種情況時存在的問題嗎?這樣我們才能夠調整和改進答案來處理你所提到的情況。 - guest271314
'q=foo%20bar#baz'.match(/q=\w+.*/)[0].split(/q=|&.*|\+/).filter(Boolean) 的输出结果是 ['foo%20bar#baz'] 而不是 ['foo', 'bar']。但请注意,我对你的解决方案没有进一步的兴趣。我已经提供了一个全面的答案,你可以参考它来理解需要解决的所有细节。 - zzzzBov
@zzzzBov,就编码问题提出你的观点。有趣的是,你的回答没有提到你对当前回答所下的反对票的情况?你回答了实际问题,并使用了实际问题中提供的字符串。并不否认你关于查询字符串中可能包含的每种字符串情况都是正确的;但原始问题并没有询问如何处理可能查询字符串的每种可能情况。不确定为什么你试图将实际原始问题扩展为一个关于查询字符串的每种可能表示的全面调查? - guest271314
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接