2

I'm processing a single string which contains many pairs of data. Each pair is separated by a ; sign. Each pair contains a number and a string, separated by an = sign.

I thought it would be easy to process, but i've found that the string half of the pair can contain the = and ; sign, making simple splitting unreliable.

Here is an example of a problematic string:

123=one; two;45=three=four;6=five;

For this to be processed correctly I need to split it up into an array that looks like this:

'123', 'one; two'
'45',  'three=four'
'6',   'five'

I'm at a bit of dead end so any help is appreciated.

UPDATE:

Thanks to everyone for the help, this is where I am so far:

$input = '123=east; 456=west';

// split matches into array
preg_match_all('~(\d+)=(.*?);(?=\s*(?:\d|$))~', $input, $matches);

$newArray = array();

// extract the relevant data
for ($i = 0; $i < count($matches[2]); $i++) {
    $type   = $matches[2][$i];
    $price  = $matches[1][$i];

    // add each key-value pair to the new array
    $newArray[$i] = array(
        'type'      => "$type",
        'price'     => "$price"
    );
}

Which outputs

Array
(
    [0] => Array
        (
            [type] => east
            [price] => 123
        )

)

The second item is missing as it doesn't have a semicolon on the end, i'm not sure how to fix that.

I've now realised that the numeric part of the pair sometimes contains a decimal point, and that the last string pair does not have a semicolon after it. Any hints would be appreciated as i'm not having much luck.

Here is the updated string taking into account the things I missed in my initial question (sorry):

12.30=one; two;45=three=four;600.00=five
5
  • You want to have a flat array of 6 elements? Commented Apr 19, 2013 at 6:22
  • Also, if a ; appears in the pair, is it always followed by a space? Commented Apr 19, 2013 at 6:30
  • I'm using array_combine to sort the array the way I want, which is [123] => one; two; and so on. ; and = in the pair won't always be followed by a space. Thanks. Commented Apr 19, 2013 at 7:21
  • Ok i'm not longer using array_combine as it messes up the order of the results. Instead i'm iterating through the matches array and creating a new array with the correct key-value pairs and in the correct order. Commented Apr 19, 2013 at 8:40
  • I've updated my post with my current code - cheers! Commented Apr 19, 2013 at 8:52

5 Answers 5

1

You need a look-ahead assertion for this; the look-ahead matches if a ; is followed by a digit or the end of your string:

$s = '12.30=one; two;45=three=four;600.00=five';

preg_match_all('/(\d+(?:.\d+)?)=(.+?)(?=(;\d|$))/', $s, $matches);

print_r(array_combine($matches[1], $matches[2]));

Output:

Array
(
    [12.30] => one; two
    [45] => three=four
    [600.00] => five
)
Sign up to request clarification or add additional context in comments.

Comments

1

I think this is the regex you want:

\s*(\d+)\s*=(.*?);(?=\s*(?:\d|$))

The trick is to consider only the semicolon that's followed by a digit as the end of a match. That's what the lookahead at the end is for.

You can see a detailed visualization on www.debuggex.com.

1 Comment

Thanks, that works well, although i've now realised that the numeric part of the pair sometimes contains a decimal point, and that the last string pair does not have a semicolon after it. Any hints would be appreciated, i'm playing around in RegexBuddy but not getting very far. Cheers.
1

You can use following preg_match_all code to capture that:

$str = '123=one; two;45=three=four;6=five;';
if (preg_match_all('~(\d+)=(.+?);(?=\d|$)~', $str, $arr))
   print_r($arr);

Live Demo: http://ideone.com/MG3BaO

Comments

1
$str = '123=one; two;45=three=four;6=five;';

preg_match_all('/(\d+)=([a-zA-z ;=]+)/', $str,$matches);
echo '<pre>';
print_r($matches);
echo '</pre>';

o/p:

Array
(
    [0] => Array
        (
            [0] => 123=one; two;
            [1] => 45=three=four;
            [2] => 6=five;
        )

    [1] => Array
        (
            [0] => 123
            [1] => 45
            [2] => 6
        )

    [2] => Array
        (
            [0] => one; two;
            [1] => three=four;
            [2] => five;
        )

)

then y can combine

echo '<pre>';
print_r(array_combine($matches[1],$matches[2]));
echo '</pre>';

o/p:

Array
(
    [123] => one; two;
    [45] => three=four;
    [6] => five;
)

Comments

0

Try this but this code is written in c#, you can change it into php

 string[] res = Regex.Split("123=one; two;45=three=four;6=five;", @";(?=\d)");

--SJ

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.