<p>I need to support exact phrases (enclosed in quotes) in an otherwise space-separated list of terms.
Thus splitting the respective string by the space-character is not sufficient anymore.</p>

<p>Example:</p>

<pre><code>input : 'foo bar "lorem ipsum" baz'
output: ['foo', 'bar', 'lorem ipsum', 'baz']
</code></pre>

<p>I wonder whether this could be achieved with a single RegEx, rather than performing complex parsing or split-and-rejoin operations.</p>

<p>Any help would be greatly appreciated!</p>

[{'answer_id': 65033, 'author': 'shyam', 'author_id': 7616, 'author_profile': 'https://Stackoverflow.com/users/7616', 'pm_score': 1, 'selected': False, 'text': '<pre><code>\'foo bar "lorem ipsum" baz\'.match(/"[^"]*"|\\w+/g);\n</code></pre>\n\n<p>the bounding quotes get included though</p>\n'}, {'answer_id': 65085, 'author': 'A Nony Mouse', 'author_id': 7182, 'author_profile': 'https://Stackoverflow.com/users/7182', 'pm_score': 2, 'selected': False, 'text': '<p>A simple regular expression will do but leave the quotation marks. e.g.</p>\n\n<pre><code>\'foo bar "lorem ipsum" baz\'.match(/("[^"]*")|([^\\s"]+)/g)\noutput:   [\'foo\', \'bar\', \'"lorem ipsum"\', \'baz\']\n</code></pre>\n\n<p>edit: beaten to it by shyamsundar, sorry for the double answer</p>\n'}, {'answer_id': 65092, 'author': 'davidnicol', 'author_id': 7420, 'author_profile': 'https://Stackoverflow.com/users/7420', 'pm_score': 1, 'selected': False, 'text': '<p>how about,</p>\n\n<pre><code>output = /(".+?"|\\w+)/g.exec(input)\n</code></pre>\n\n<p>then do a pass on output to lose the quotes.</p>\n\n<p>alternately,</p>\n\n<pre><code>output = /"(.+?)"|(\\w+)/g.exec(input)\n</code></pre>\n\n<p>then do a pass n output to lose the empty captures.</p>\n'}, {'answer_id': 65177, 'author': 'yoz', 'author_id': 9070, 'author_profile': 'https://Stackoverflow.com/users/9070', 'pm_score': 5, 'selected': True, 'text': '<pre><code>var str = \'foo bar "lorem ipsum" baz\';  \nvar results = str.match(/("[^"]+"|[^"\\s]+)/g);\n</code></pre>\n\n<p>... returns the array you\'re looking for.<br>\nNote, however:</p>\n\n<ul>\n<li>Bounding quotes are included, so can be removed with <code>replace(/^"([^"]+)"$/,"$1")</code> on the results.</li>\n<li>Spaces between the quotes will stay intact. So, if there are three spaces between <code>lorem</code> and <code>ipsum</code>, they\'ll be in the result. You can fix this by running <code>replace(/\\s+/," ")</code> on the results.</li>\n<li>If there\'s no closing <code>"</code> after <code>ipsum</code> (i.e. an incorrectly-quoted phrase) you\'ll end up with: <code>[\'foo\', \'bar\', \'lorem\', \'ipsum\', \'baz\']</code></li>\n</ul>\n'}, {'answer_id': 65338, 'author': 'Sam Hasler', 'author_id': 2541, 'author_profile': 'https://Stackoverflow.com/users/2541', 'pm_score': 2, 'selected': False, 'text': '<p>Try this:</p>\n\n<pre><code>var input = \'foo bar "lorem ipsum" baz\';\nvar R =  /(\\w|\\s)*\\w(?=")|\\w+/g;\nvar output = input.match(R);\n\noutput is ["foo", "bar", "lorem ipsum", "baz"]\n</code></pre>\n\n<p>Note there are no extra double quotes around lorem ipsum</p>\n\n<p>Although it assumes the input has the double quotes in the right place:</p>\n\n<pre><code>var input2 = \'foo bar lorem ipsum" baz\'; var output2 = input2.match(R);\nvar input3 = \'foo bar "lorem ipsum baz\'; var output3 = input3.match(R);\n\noutput2 is ["foo bar lorem ipsum", "baz"]\noutput3 is ["foo", "bar", "lorem", "ipsum", "baz"]\n</code></pre>\n\n<p>And won\'t handle escaped double quotes (is that a problem?):</p>\n\n<pre><code>var input4 = \'foo b\\"ar  bar\\" \\"bar "lorem ipsum" baz\';\nvar output4 = input4.match(R);\n\noutput4 is  ["foo b", "ar bar", "bar", "lorem ipsum", "baz"]\n</code></pre>\n'}, {'answer_id': 65577, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>Thanks a lot for the quick responses!</p>\n\n<p>Here\'s a summary of the options, for posterity:</p>\n\n<pre><code>var input = \'foo bar "lorem ipsum" baz\';\n\noutput = input.match(/("[^"]+"|[^"\\s]+)/g);\noutput = input.match(/"[^"]*"|\\w+/g);\noutput = input.match(/("[^"]*")|([^\\s"]+)/g)\noutput = /(".+?"|\\w+)/g.exec(input);\noutput = /"(.+?)"|(\\w+)/g.exec(input);\n</code></pre>\n\n<p>For the record, here\'s the abomination I had come up with:</p>\n\n<pre><code>var input = \'foo bar "lorem ipsum" "dolor sit amet" baz\';\nvar terms = input.split(" ");\n\nvar items = [];\nvar buffer = [];\nfor(var i = 0; i &lt; terms.length; i++) {\n    if(terms[i].indexOf(\'"\') != -1) { // outer phrase fragment -- N.B.: assumes quote is either first or last character\n        if(buffer.length === 0) { // beginning of phrase\n            //console.log("start:", terms[i]);\n            buffer.push(terms[i].substr(1));\n        } else { // end of phrase\n            //console.log("end:", terms[i]);\n            buffer.push(terms[i].substr(0, terms[i].length - 1));\n            items.push(buffer.join(" "));\n            buffer = [];\n        }\n    } else if(buffer.length != 0) { // inner phrase fragment\n        //console.log("cont\'d:", terms[i]);\n        buffer.push(terms[i]);\n    } else { // individual term\n        //console.log("standalone:", terms[i]);\n        items.push(terms[i]);\n    }\n    //console.log(items, "\\n", buffer);\n}\nitems = items.concat(buffer);\n\n//console.log(items);\n</code></pre>\n'}, {'answer_id': 16945284, 'author': 'tigerswithguitars', 'author_id': 726986, 'author_profile': 'https://Stackoverflow.com/users/726986', 'pm_score': 0, 'selected': False, 'text': '<p>One that\'s easy to understand and a general solution. Works for all delimiters and \'join\' characters. Also supports \'joined\' words that are more than two words in length.... ie lists like </p>\n\n<p><code>"hello my name is \'jon delaware smith fred\' I have a \'long name\'"</code>....</p>\n\n<p>A bit like the answer by AC but a bit neater...</p>\n\n<pre><code>function split(input, delimiter, joiner){\n    var output = [];\n    var joint = [];\n    input.split(delimiter).forEach(function(element){\n        if (joint.length &gt; 0 &amp;&amp; element.indexOf(joiner) === element.length - 1)\n        {\n            output.push(joint.join(delimiter) + delimiter + element);\n            joint = [];\n        }\n        if (joint.length &gt; 0 || element.indexOf(joiner) === 0)\n        {\n            joint.push(element);\n        }\n        if (joint.length === 0 &amp;&amp; element.indexOf(joiner) !== element.length - 1)\n        {\n            output.push(element);\n            joint = [];\n        }\n    });\n    return output;\n  }\n</code></pre>\n'}, {'answer_id': 26626761, 'author': 'Suganthan Madhavan Pillai', 'author_id': 2534236, 'author_profile': 'https://Stackoverflow.com/users/2534236', 'pm_score': 0, 'selected': False, 'text': '<p>This might be a very late answer, but I am interested in answering</p>\n\n<pre><code>([\\w]+|\\"[\\w\\s]+\\")\n</code></pre>\n\n<p><a href="http://regex101.com/r/dZ1vT6/72" rel="nofollow">http://regex101.com/r/dZ1vT6/72</a></p>\n\n<p>Pure javascript example</p>\n\n<pre><code> \'The rain in "SPAIN stays" mainly in the plain\'.match(/[\\w]+|\\"[\\w\\s]+\\"/g)\n</code></pre>\n\n<p>Outputs:</p>\n\n<pre><code>["The", "rain", "in", ""SPAIN stays"", "mainly", "in", "the", "plain"]\n</code></pre>\n'}, {'answer_id': 46946542, 'author': 'Tsuneo Yoshioka', 'author_id': 1309218, 'author_profile': 'https://Stackoverflow.com/users/1309218', 'pm_score': 1, 'selected': False, 'text': '<p>ES6 solution supporting:</p>\n\n<ul>\n<li>Split by space except for inside quotes</li>\n<li>Removing quotes but not for backslash escaped quotes</li>\n<li>Escaped quote become quote</li>\n</ul>\n\n<p>Code:</p>\n\n<pre><code>input.match(/\\\\?.|^$/g).reduce((p, c) =&gt; {\n        if(c === \'"\'){\n            p.quote ^= 1;\n        }else if(!p.quote &amp;&amp; c === \' \'){\n            p.a.push(\'\');\n        }else{\n            p.a[p.a.length-1] += c.replace(/\\\\(.)/,"$1");\n        }\n        return  p;\n    }, {a: [\'\']}).a\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>[ \'foo\', \'bar\', \'lorem ipsum\', \'baz\' ]\n</code></pre>\n'}, {'answer_id': 64447893, 'author': 'Rob Hawkins', 'author_id': 2636364, 'author_profile': 'https://Stackoverflow.com/users/2636364', 'pm_score': 0, 'selected': False, 'text': '<p>Expanding on the accepted answer, here\'s a search engine parser that,</p>\n<ul>\n<li>can match phrases or words</li>\n<li>treats phrases as regular expressions</li>\n<li>does a boolean OR across multiple properties (e.g. item.title and item.body)</li>\n<li>handles negation of words or phrases when they are prefixed with -</li>\n</ul>\n<p>Treating phrases as regular expressions makes the UI simpler for my purposes.</p>\n<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">\r\n<div class="snippet-code">\r\n<pre class="snippet-code-js lang-js prettyprint-override"><code>const matchOrIncludes = (str, search, useMatch = true) =&gt; {\n  if (useMatch) {\n    let result = false\n    try {\n      result = str.match(search)\n    } catch (err) {\n      return false\n    }\n    return result\n  }\n  return str.includes(search)\n}\n\n\nconst itemMatches = (item, searchString, fields) =&gt; {\n  const keywords = searchString.toString().replace(/\\s\\s+/g, \' \').trim().toLocaleLowerCase().match(/(-?"[^"]+"|[^"\\s]+)/g) || []\n  for (let i = 0; i &lt; keywords.length; i++) {\n    const negateWord = keywords[i].startsWith(\'-\') ? true : false\n    let word = keywords[i].replace(/^-/,\'\')\n    const isPhraseRegex = word.startsWith(\'"\') ? true : false\n    if (isPhraseRegex) {\n      word = word.replace(/^"(.+)"$/,"$1")\n    }\n    let word_in_item = false\n    for (const field of fields) {\n      if (item[field] &amp;&amp; matchOrIncludes(item[field].toLocaleLowerCase(), word, isPhraseRegex)) {\n        word_in_item = true\n        break\n      }\n    }\n    if ((! negateWord &amp;&amp; ! word_in_item) || (negateWord &amp;&amp; word_in_item)) {\n      return false\n    }\n  }\n  return true\n}\n\nconst item = {title: \'My title\', body: \'Some text\'}\nconsole.log(itemMatches(item, \'text\', [\'title\', \'body\']))</code></pre>\r\n</div>\r\n</div>\r\n</p>\n'}]
['https://Stackoverflow.com/questions/64904', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/-1/']