4

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

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Yannik
  • 43
  • 8
  • Try `preg_match_all('~(?|"([^\\\\"]*(?:\\\\.[^"\\\\]*)*)"|([^\s"]+))~s', $s, $matches)`. Then check the result with `print_r($matches[1])`. If you need the substrings with quotes, you will get them with `preg_match_all('~"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|[^\s"]+~s', $s, $matches)` and `print_r($matches[0])`. – Wiktor Stribiżew Jun 05 '19 at 11:16
  • Which one? 1) or 2) – Wiktor Stribiżew Jun 05 '19 at 12:08
  • Both but for my case, the first ;) – Yannik Jun 05 '19 at 12:16
  • No need to add SOLVED to the question, you marked an answer as a solution, so the question is marked as answered by SO. I rolled back that edit. – Wiktor Stribiżew Jun 05 '19 at 12:24

3 Answers3

3

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 )
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
0

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>";
?>
Rakesh P
  • 438
  • 5
  • 19
0

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.

kainaw
  • 4,256
  • 1
  • 18
  • 38