PHP explode strings, but treat words in quotes as a single word

Viewed 94

How can I explode the following string:

"foo bar"ANDbar"foo"AND"foofoo" lorem "impsum"

into

array('"foo bar"', 'ANDbar', '"foo"', 'AND',' "foofoo"', "lorem", '"impsum"')

I check this answer : https://stackoverflow.com/a/2202489/11398085 but not work without the space link in my string.

$text = '"foo bar"ANDbar"foo"AND"foofoo" lorem "impsum"';
preg_match_all('/"(?:\\\\.|[^\\\\"])*"|\S+/', $text, $matches);
print_r($matches);

Results :

0 => array:7 [
 0 => ""foo bar""
    1 => "ANDbar"foo"AND"foofoo""
    2 => "lorem"
    3 => ""impsum""
  ]

But i need this :

0 => array:7 [
 0 => ""foo bar""
    1 => "ANDbar"
    2 => ""foo""
    3 => "AND"
    4 => ""foofoo""
    5 => "lorem"
    6 => ""impsum""
  ]

Thanks :D

3 Answers

You may use

if (preg_match_all('~(?|"([^\\\\"]*(?:\\\\.[^"\\\\]*)*)"|([^\s"]+))~s', $s, $matches)) 
{
    print_r($matches[1]);
}

See the regex demo.

Details

  • (?| - starts a branch reset group:
    • " - a " char
    • ([^\\\\"]*(?:\\\\.[^"\\\\]*)*) - Group 1: any 0+ chars other than \ and " followed with 0 or more repetitions of any escaped char and then any 0+ chars other than \ and "
    • " - a " char
  • | - or
    • ([^\s"]+) - Group 1: one or more chars other than whitespace and "
  • ) - end of the branch reset group.

See the PHP demo:

$s = '"foo bar"ANDbar"foo"AND"foofoo" lorem "impsum"';
if (preg_match_all('~(?|"([^\\\\"]*(?:\\\\.[^"\\\\]*)*)"|([^\s"]+))~s', $s, $matches)) 
{
    print_r($matches[1]);
}
// => Array ( [0] => foo bar [1] => ANDbar [2] => foo [3] => AND [4] => foofoo [5] => lorem [6] => impsum )

You may use:

<?php

$orgstr = '"foo bar"ANDbar"foo"AND"foofoo" lorem "impsum"';
$org_arr = explode('"',$orgstr);

$chk = 0;
$new_arr = array();
foreach($org_arr as $k=>$val){
     if($val=='') continue;
     if($chk%2==0) array_push($new_arr,'""'.trim($val).'""'); else array_push($new_arr,'"'.trim($val).'"');
     $chk++;
}

echo "<br><pre>";
print_r($new_arr);
echo "</pre>";
?>

It looks like you want to explode on quotes (ignoring the first and last quote) and then place quotes around elements 1, 3, 5... and trim whitespace from elements 2, 4, 6... If that is the case, you can do exactly that:

$str = '"foo bar"ANDbar"foo"AND"foofoo" lorem "impsum"';
// ignore first/last quote:
$str = trim($str, '"');
// explode on quotes
$a = explode('"', $str);
foreach($a as $i=>$v) {
  // Place quotes around indexes 1, 3, 5...
  if($i%2 == 1) $a[$i] = '"'.$v.'"';
  // Trim whitespace around indexes 2, 4, 6...
  if($i%2 == 0) $a[$i] = trim($v);
}

You can combine those functions to make it shorter, but I wanted to make sure you could see that it is doing exactly what you appear to be asking for.

Related