5

I have this query string www.example.com/yy?q=how+can+i+get+this&o=1&source=home

How can I parse just the q parameter value in a array with javascript or jquery ?

I want the array like this

['how', 'can', 'i', 'get', 'this']
Kenster
  • 23,465
  • 21
  • 80
  • 106
Hayi
  • 6,972
  • 26
  • 80
  • 139

3 Answers3

2

Assuming that the order of your query strings aren't always going to be known and that you have to support finding 'q' anywhere;

// 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;
  }
}
diadical
  • 197
  • 4
  • it return `['q=how', 'can', 'i', 'get', 'this']` – Hayi May 24 '15 at 23:02
  • i replace last line with `var qArray = q[0].replace('q=','').split('+');` and it works – Hayi May 24 '15 at 23:41
  • I've updated it with a extra substring call to skip those characters, replace works as well but will not stop at the first instance is that string so isn't as clean. – diadical May 25 '15 at 00:40
  • thanks but i chose to do it with loop can u update your answer to stop at the first instance like this `for (var i in queryStrings) { if( queryStrings[i].substring(0, 2) === 'q=' ){ array = queryStrings[i].replace('q=','').split('+'); break; } }` – Hayi May 26 '15 at 14:25
  • 1
    I've updated it to do the for loop, you'll notice though that I'm using for instead of for...in. For in can be dangerous over regular arrays for a few reasons and while some of those are no longer a problem in modern browsers if you are using libraries that extend the base array object (i.e. shims or certain frameworks) then you'll have a bug. Those properties will be iterated over as if they were indexes. Try to use for...in for object iteration, [see here](https://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea/500531#500531). – diadical May 27 '15 at 14:23
  • If the URL contains `%20` instead of `+`, or if the URL contains *any* percent-encoded characters, this solution will fail. – zzzzBov Sep 05 '16 at 20:51
2

Your question really a combination of a series of questions that each need to be answered to move to the next part.

You asked how to pull the q parameter out of the query string and split it on spaces, but this overlooks the fact that you first need to parse the URL.

Part 1: Parsing a URL Into Parts

You tagged , which is completely 100% unnecessary. However, this does tell me that you're working in a browser environment rather than server-side JavaScript, which means that we can use a few tricks to parse URLs that aren't available in .

If you know you want to get the query string from the current URL, you can simply access location.search

If you have a URL string and you want to get the query string, you can use an a element to do the parsing automatically for you. Refer to link anatomy to see which parts of the URL are which:

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
  };
}

At this point it's worth noting that the url given (www.example.com/yy?q=how+can+i+get+this&o=1&source=home) is malformed, and missing the protocol, which means that parsing it will result in the pathname being treated as a relative path from the current URL. To fix this, prefix the URL with 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);

Part 2: Parsing the Query String Into Parts

This part is easy to mess up because query strings are hard (full disclosure, I wrote that blog post).

Anyone attempting to parse a query string using a regular expression is probably wrong in many ways.

My recommendation is don't reinvent the wheel. I wrote a QueryString parser, which is available with an MIT license, or if you're not comfortable with my attempt at a solution, consider using the querystring module from , which is available with .

The module I wrote myself uses UMD, so it should be compatible with most projects regardless of what you're using (or not using) for bundling and dependency management.

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>

Part 3: Splitting a string on spaces

This part is deceptively easy. It would be easy to tell you to use:

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

But that's likely not actually what you want. If you want to also split on tabs, or newlines, it's more complicated. You probably also want to avoid empty strings in the array as well (' foo bar ' would have 3 empty strings). Without knowing your intention, it's hard to recommend a course of action. Generally, splitting using a regular expression along the lines of /\s+/g and then filtering any possible leading and trailing empty strings is a more resilient solution:

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

Part 4: All Together Now

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>

Now this may seem like a bunch of work, and it is. It's unfortunate that JS doesn't have a lot of native support for some of these commonly used features. UrlSearchParams has partial browser support, but even that has issues parsing query strings.

Just be sure that you're handling each of these pieces correctly, otherwise a user can simply change the URL to your page and likely have it crash in unexpected ways.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • Note, stacksnippets is logging error `{ "message": "Uncaught TypeError: Cannot read property 'split' of undefined", "filename": "http://stacksnippets.net/js", "lineno": 46, "colno": 5 }` – guest271314 Sep 06 '16 at 01:23
  • @guest271314, and which browser/version are you using? I'm not able to reproduce that one. – zzzzBov Sep 06 '16 at 02:37
  • chromium. Believe it is due to `.search` ? Where result is empty string when trying example URL at this Question http://stackoverflow.com/questions/39339248/update-uri-hash-javascript . https://jsfiddle.net/hokqjgpj/ – guest271314 Sep 06 '16 at 02:40
  • Is `qs.parse(parts.search);` or `queryString .q .split(/\s+/g)` call causing this? – guest271314 Sep 06 '16 at 02:46
  • @guest271314, oh, if you're editing the snippet and removing the querystring then yes, you're going to need to make sure you perform standard input checking. It should be obvious that `({}).q.split()` would error because the empty object has no `q` property. I'll go ahead and update the code to address this particular issue, but it's not an error in the example as-written. – zzzzBov Sep 06 '16 at 02:55
  • No, did not remove any portion of your snippet. Only input string from linked Question. Linked to your Answer above from Question due to believing that your Answer was comprehensive enough to handle any input string, following our earlier communications. Tried string from other Question and encountered error. _"but it's not an error in the example as-written"_. Well, neither was own Answer, below, as written for this specific Question. – guest271314 Sep 06 '16 at 03:00
  • @guest271314, it sounds like you don't understand where `q=foo%20bar#baz` would go in my example. It's not a query string unless it's prefixed by `?`. Otherwise, it's a relative path. If you just wanted to parse `'q=foo%20bar#baz'`, then you could use `qs.parse('q=foo%20bar#baz')`, and you'd see that it returns the correct result. – zzzzBov Sep 06 '16 at 03:16
  • _"it sounds like you don't understand where `q=foo%20bar#baz` would go in my example."_ It is not that your example or point is misunderstood. From this standpoint your example is beyond the scope of the actual original Question. Perhaps you believe that the Question is broader than the text it contains, or that the Answers to the Question, as written, should handle every possible query string, including encoded phrases. The actual original Question does not present that inquiry. Do not have an issue with your Answer. "downvote" at own Answer was not warranted given actual original Question. – guest271314 Sep 06 '16 at 03:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/122753/discussion-between-zzzzbov-and-guest271314). – zzzzBov Sep 06 '16 at 13:59
0

Try utilizing String.prototype.match() on input string str , with RegExp argument /q=\w+.*/ to match string beginning with "q=" ; call .split() on string item at index 0 of returned array from .match() with RegExp parameter /q=|&.*|\+|#|%20/ ; call .filter() to removing empty items from array returned by .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));
guest271314
  • 1
  • 15
  • 104
  • 177
  • @Kenster Was not aware of that. Is that reason for "downvote"? – guest271314 Sep 05 '16 at 16:09
  • 1
    @guest271314, downvote mine, only just had the time to come back and answer this question appropriately. Your answer fails to decode the query string values appropriately, and if there's a hash in the URL, it would be included in the regular expression match for that parameter. – zzzzBov Sep 05 '16 at 20:54
  • @zzzzBov Can you share an example of issue with at approach at Answer that you are describing? To be able to adjust and improve Answer to handle the case you are referencing? – guest271314 Sep 05 '16 at 21:18
  • `'q=foo%20bar#baz'.match(/q=\w+.*/)[0].split(/q=|&.*|\+/).filter(Boolean)` produces `['foo%20bar#baz']` rather than `['foo', 'bar']`. But please be aware I have no further interest in debugging your solution. I have provided a comprehensive answer of my own, which you should be able to reference to understand all the details that would need to be addressed. – zzzzBov Sep 05 '16 at 21:28
  • @zzzzBov `'q=foo%20bar#baz'` is not query string at actual Question. _"I have no further interest in debugging your solution"_ Then why "downvote"? If you are not interested in correcting issues which you have created, why create issue that is not present at actual Question? Your Answer would probably be best suited as a canonical Question/Answer; rather than revision of original Question and previously posted Answers? The "downvote" is not warranted. Kindly withdraw "downvote", as Answer provided answers actual Question posted by OP. – guest271314 Sep 05 '16 at 21:36
  • @zzzzBov fwiw, updated Answer to address case you described. `"q=foo%20bar#baz".match(/q=\w+.*/)[0].split(/q=|&.*|\+|#|%20/).filter(Boolean);` – guest271314 Sep 05 '16 at 22:10
  • @guest271314, adding `%20` shows that you truly don't understand how percent encoding works. Have fun adding support for `%00` - `%FF` to your regex. – zzzzBov Sep 05 '16 at 22:53
  • @zzzzBov Gather your point concerning encoding. Interesting that your Answer does not mention the case which you downvoted the present Answer for? You answered the actual Question, using the string provided at actual Question. Not disputing that your point is correct concerning every case of string which could be within a query string; though the original Question does not ask how to handle every possible case of a possible query string. Not certain why you have attempted to extend the actual original Question to be a comprehensive inquiry into every possible representation of a query string? – guest271314 Sep 05 '16 at 23:05