-1

I need to split a PHP array into an array containing text and URLs. For instance, assuming

$string = "Hello, my name is http://www.audio.com/1234.mp3/. Today is https://radio.org/weather.wav";

The expected output should be something like:

$a[0] = "Hello, my name is";
$a[1] = "http://www.audio.com/1234.mp3/";
$a[2] = ". Today is";
$a[3] = "https://radio.org/weather.wav";
3
  • 2
    Why do you need it like this? If you want to convert the urls to links, it's easier to use preg_replace Commented Feb 26, 2011 at 18:31
  • 1
    See stackoverflow.com/questions/287144/… for example. Commented Feb 26, 2011 at 18:33
  • My goal is to produce a function that reads text out loud, replacing text by already existing audio files whenever appropriate. For instance, Say("hello $name!"); might produce different results whether $name is text or the url of a sound file... Commented Feb 27, 2011 at 14:28

2 Answers 2

1

You cannot split it easily. But a workaround would be to match it in pairs using something like:

preg_match_all('#(.*?)(https?://\S+(?<![,.]))\K#s', $str, $m,
               PREG_SET_ORDER);
$list = call_user_func_array("array_merge", $m);

The call_user_func_array is another workaround to avoid flatteing the array manually. This method will lead to empty entries in between however:

Array
(
    [0] => 
    [1] => Hello, my name is 
    [2] => http://www.audio.com/1234.mp3/
    [3] => 
    [4] =>  Today is 
    [5] => https://radio.org/weather.wav
)

Also note that the simplistic URL regex ate up the period. (Use exact character groups instead of lookbehind.)

Sign up to request clarification or add additional context in comments.

5 Comments

There is preg_split(), which has a few options to capture delimiters and whatnot as well.
Thanks so much for your answer and comments, mario and Mark B! How difficult would it be to get the punctuation (!.,?;) after the url? Is that possible at all? As mentioned above, my goal is to produce a function that reads text out loud, replacing text by already existing audio files whenever appropriate. For instance, Say("hello $name!"); might produce different results whether $name is text or the url of a sound file. If that's not possible, one alternative would be to require urls to always have a space after them... Would that make sense?
@user362794: You could indeed use preg_split as Marc said. It might return the desired result without workarounds: $list = preg_split('#(https?://\S+(?<![,.]))#', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
@mario and @MarcB, Sorry for the additional questions, but what do I need to do in order to prevent punctuation such as ! ? ; : from being included in the parsed URL? Any ideas? That's the sort of thing that might happen in situations such as Say("Hi $audio_name_url!"); or Say("Weather for $location: $weather."); ... Thanks once again!
@elbee: Extend the negative lookbehind assertion (?<![,?...]). See regular-expressions.info/lookaround.html -- Btw, only one @notification per comment works.
0

Directly populate the desired result by calling preg_split() and including the delimiting URL substrings in the flat output array. Write \s* to optionally match zero or more whitespaces before or after the URLs -- this will exclude unwanted/trimmable whitespaces from the array values.

Code: (Demo)

$string = "Hello, my name is http://www.audio.com/1234.mp3/. Today is https://radio.org/weather.wav";
var_export(
    preg_split(
        '#\s*(https?://\S+(?<![,.]))\s*#',
        $string,
        flags: PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
    )
);

Output:

array (
  0 => 'Hello, my name is',
  1 => 'http://www.audio.com/1234.mp3/',
  2 => '. Today is',
  3 => 'https://radio.org/weather.wav',
)

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.