split

(PHP 4, PHP 5)

splitSepara strings em array utilizando expressões regulares

Aviso

Esta função está OBSOLETA no PHP 5.3.0 e foi REMOVIDA no PHP 7.0.0.

Alternativas a esta função incluem:

Descrição

split ( string $pattern , string $string [, int $limit = -1 ] ) : array

Separa uma string em array por expressão regular.

Parâmetros

pattern

A expressão regular case sensitive.

Se separar caracteres que são consideredos especiais para as expressões regulares, será necessário usar o caracter de escape primeiramente. Se você pensar que split() (ou outra função para execução de expressões regulares) é muito estranha, por favor leia o arquivo regex.7, incluido na pasta regex/ no subdiretório da distribuição do PHP. Está no formato manpage e você deverá usar o comando man /usr/local/src/regex/regex.7 para maiores informações.

string

A string de entrada.

limit

Se limit é definido, o array retornado conterá no máximo de limit elementos, sendo que o último elemento conterá o resto da string.

Valor Retornado

Retorna uma matriz de strings, contendo as substrings de string separadas pelos limites descritos na expressão regular pattern.

Se existirem n ocorrências da pattern, será retornado uma matriz (array) contendo n+1 items. Por exemplo, se não existir uma ocorrência de pattern, uma matriz com um único elemento será retornado. Certamente, isto também é válido se string estiver vazia. Se um erro ocorrer, split() retorna FALSE.

Exemplos

Exemplo #1 Exemplo da split()

Separa os quatro primeiro elementos de uma linha do arquivo /etc/passwd:

<?php
list($user$pass$uid$gid$extra) =
    
split(":"$passwd_line5);
?>

Exemplo #2 Exemplo da split()

Separação de dados delimitados por barras, pontos, ou traços:

<?php
// Delimitado por barras, pontos ou traços
$data "04/30/1973";
list (
$mes$dia$ano) = split ('[/.-]'$data);
echo 
"Mês: $mes; Dia: $dia; Ano: $ano<br />\n";
?>

Notas

Dica

A função split() está obsoleta desde o PHP 5.3.0. preg_split() é a alternativa sugerida. Se você não precisa do poder das expressões regulares, é mais eficiente usar explode(), que não faz overhead de um engine de expressão regular.

Dica

Para visualizar uma emulação do Perl e seus métodos @chars = split('', $str), veja os exemplos das funções preg_split() ou str_split().

Veja Também

  • preg_split() - Divide a string por uma expressão regular
  • spliti() - Separa strings em array utilizando expressões regulares insensíveis a maiúsculas e minúsculas
  • str_split() - Converte uma string para um array
  • explode() - Divide uma string em strings
  • implode() - Junta elementos de uma matriz em uma string
  • chunk_split() - Divide uma string em pequenos pedaços
  • wordwrap() - Quebra uma string em um dado número de caracteres

add a note add a note

User Contributed Notes 25 notes

up
5
Dave Walter
16 years ago
In response to  the getCSVValues() function posted by justin at cam dot org, my testing indicates that it has a problem with a CSV string like this:

1,2,"3,""4,5"",6",7

This parses as:

array(6) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
  [2]=>
  string(4) "3,"4"
  [3]=>
  string(1) "5"
  [4]=>
  string(0) ""
  [5]=>
  string(1) "7"
}

instead of:

array(4) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
  [2]=>
  string(9) "3,"4,5",6"
  [3]=>
  string(1) "7"
}

To fix this, I changed the second substr_count to look for an odd number of quotes, as opposed to any quotes at all:

<?php
function getCSVValues($string, $separator=",")
{
   
$elements = explode($separator, $string);
    for (
$i = 0; $i < count($elements); $i++) {
       
$nquotes = substr_count($elements[$i], '"');
        if (
$nquotes %2 == 1) {
            for (
$j = $i+1; $j < count($elements); $j++) {
                if (
substr_count($elements[$j], '"') %2 == 1) { // Look for an odd-number of quotes
                    // Put the quoted string's pieces back together again
                   
array_splice($elements, $i, $j-$i+1,
                       
implode($separator, array_slice($elements, $i, $j-$i+1)));
                    break;
                }
            }
        }
        if (
$nquotes > 0) {
           
// Remove first and last quotes, then merge pairs of quotes
           
$qstr =& $elements[$i];
           
$qstr = substr_replace($qstr, '', strpos($qstr, '"'), 1);
           
$qstr = substr_replace($qstr, '', strrpos($qstr, '"'), 1);
           
$qstr = str_replace('""', '"', $qstr);
        }
    }
    return
$elements;
}
?>
up
1
wchris
19 years ago
moritz's quotesplit didn't work for me. It seemed to split on a comma even though it was between a pair of quotes. However, this did work:

function quotesplit($s, $splitter=',')
{
//First step is to split it up into the bits that are surrounded by quotes and the bits that aren't. Adding the delimiter to the ends simplifies the logic further down

    $getstrings = split('\"', $splitter.$s.$splitter);

//$instring toggles so we know if we are in a quoted string or not
    $delimlen = strlen($splitter);
    $instring = 0;

    while (list($arg, $val) = each($getstrings))
    {
        if ($instring==1)
        {
//Add the whole string, untouched to the result array.
            $result[] = $val;
            $instring = 0;
        }
        else
        {
//Break up the string according to the delimiter character
//Each string has extraneous delimiters around it (inc the ones we added above), so they need to be stripped off
            $temparray = split($splitter, substr($val, $delimlen, strlen($val)-$delimlen-$delimlen ) );

            while(list($iarg, $ival) = each($temparray))
            {
                $result[] = trim($ival);
            }
            $instring = 1;
        }
    }
    return $result;
}
up
1
dalu at uni dot de
21 years ago
php4.3.0

strange things happen with split

this didn't work
$vontag $vonmonat were empty strings

<?php
function ckdate($fromdate="01.01", $todate="31.12")
{
   
$nowyear = date("Y");
    list (
$vontag , $vonmonat) = split ('.' , $fromdate); // << bad
   
$vondatum = "$nowyear-$vonmonat-$vontag";
    list (
$bistag , $bismonat) = split ('.' , $todate); // << bad
   
$bisdatum = "$nowyear-$bismonat-$bistag";
   
$von = strtotime($vondatum);
   
$bis = strtotime($bisdatum);
   
$now = time();
    if ((
$now <= $bis) and ($now >= $von))
    {
        return
TRUE;
    }
    else
    {
        return
FALSE;
    }
}
?>

however this one worked perfectly

<?php
function ckdate($fromdate="01.01", $todate="31.12")
{
   
$nowyear = date("Y");
    list (
$vontag , $vonmonat) = split ('[.]' , $fromdate); // << good
   
$vondatum = "$nowyear-$vonmonat-$vontag";
    list (
$bistag , $bismonat) = split ('[.]' , $todate); // << good
   
$bisdatum = "$nowyear-$bismonat-$bistag";
   
$von = strtotime($vondatum);
   
$bis = strtotime($bisdatum);
   
$now = time();
    if ((
$now <= $bis) and ($now >= $von))
    {
        return
TRUE;
    }
    else
    {
        return
FALSE;
    }
}
?>

btw this fn checks if $now if between $fromdate and $todate
use it if you like
up
0
nomail at please dot now
21 years ago
If you want to use split to check on line feeds (\n), the following won't work:

$line = split("\n", $input_several_lines_long);

You really have to do this instead, notice the second slash:
$line = split("\\n", $input_several_lines_long);

Took me a little while to figure out.
up
0
paha at paha dot hu
22 years ago
It's evident but not mentioned in the documentation that using asterisks is more restricted than in a normal regular expression.

for exaple you cannot say:

split(";*",$string);

because what if there's no ";" separator?(which is covered by this regular expression)

so you have to use at least

split(";+",$quotatxt);

in this situation.
up
-1
RE: gcerretini at technica dot net /UTF8
18 years ago
Original problem:
=================

I've try using split function.

<?php
$ferro
="2&#65533;12";
$valore=split("[&#65533;]",$ferro);
echo
$ferro."<br>";
echo
"p1-".$valore[0]."<br>";
echo
"p2-".$valore[1]."<br>";
echo
"p3-".$valore[2]."<br>";
$ferro="2d12";
$valore=split("[d]",$ferro);
echo
$ferro."<br>";
echo
"p1-".$valore[0]."<br>";
echo
"p2-".$valore[1]."<br>";
echo
"p3-".$valore[2]."<br>";
?>

This return:
============

2&#65533;12
p1-2
p2-
p3-12
2d12
p1-2
p2-12
p3-

I use charset UTF-8. When I use char &#65533; the split function ad an empty string between "2" and "12"... Why?

Explanation:
============

UTF-8 charset codes some characters (like the "&#65533;" character) into two bytes. In fact the regular expresion "[&#65533;]" contains 4 bytes (4 non-unicode characters). To demonstrate the real situation I wrote following example:

$ferro="2de12";
$valore=split("[de]",$ferro);
echo $ferro."<br>";
echo "p1-".$valore[0]."<br>";
echo "p2-".$valore[1]."<br>";
echo "p3-".$valore[2]."<br>";

This returns:
=============

2d12
p1-2
p2-
p3-12
up
-1
jeffrey at jhu dot edu
21 years ago
In answer to gwyne at gmx dot net, dec 1, 2002:

For split(), when using a backslash as the delimiter, you have to *double escape* the backslash.

example:
==================================
<pre>
<?
$line
= 'stuff\\\thing\doodad\\';
$linearray = split('\\\\', $line); //<--NOTE USE OF FOUR(4)backslashes
print join(":", $linearray);
?>
</pre>

==================================
output is:

<pre>
stuff::thing:doodad:
</pre>
up
-2
ramkumar rajendran
19 years ago
A correction to a earlier note
If you want to use split to check on line feeds (\n), the following won't work:

$line = split("\n", $input_several_lines_long);

You really have to do this instead, notice the second slash:
$line = split("/\n", $input_several_lines_long);

Took me a little while to figure to do
up
-3
franz at fholzinger dot com
19 years ago
The example from ramkumar rajendran did not work.
$line = split("/\n", $input_several_lines_long);
I do not know why this does not work for me.

The following has worked for me to get a maximum of 2 array parts separated by the first new line (independant if saved under UNIX or WINDOWS):
$line = preg_split('/[\n\r]+/',$input_several_lines_long,2);
Also empty lines are not considered here.
up
-2
krahn at niehs dot nih dot gov
21 years ago
> strange things happen with split
> this didn't work
> $vontag $vonmonat were empty strings
...
> list ($vontag , $vonmonat) = split ('.' , $fromdate); // << bad

Split is acting exactly as it should; it splits on regular expressions.
A period is a regular expression pattern for a single character.
So, an actual period must be escaped with a backslash:  '\.'
A period within brackets is not an any-character pattern, because it does
not make sense in that context.

Beware that regular expressions can be confusing becuase there
are a few different varieties of patterns.
up
-2
jchart at sdccu dot net
22 years ago
[Ed. note: Close. The pipe *is* an operator in PHP, but
the reason this fails is because it's also an operator
in the regex syntax. The distinction here is important
since a PHP operator inside a string is just a character.]

The reason your code:

$line = "12|3|Fred";
list ($msgid, $msgref, $msgtopic)=split('|', $line);

didn't work is because the "|" symbol is an operator in PHP. If you want to use the pipe symbol as a delimiter you must excape it with a back slash, "\|". You code should look like this:

$line = "12|3|Fred";
list ($msgid, $msgref, $msgtopic)=split('\|', $line);
up
-3
Jort
17 years ago
If you are looking for EITHER open square brackets OR close square brackets, then '[[]]' won't work (reasonably expected), but neither will '[\[\]]', nor with any number of escapes. HOWEVER, if your pattern is '[][]' it will work.
up
-2
mcgarry at tig dot com dot au
22 years ago
split() doesn't like NUL characters within the string, it treats the first one it meets as the end of the string, so if you have data you want to split that can contain a NUL character you'll need to convert it into something else first, eg:

$line=str_replace(chr(0),'',$line);
up
-3
Chris Tyler
16 years ago
Thank you Dave for your code below.  Here is one change I made to avoid a redundant quote at the end of some lines (at least when I used excel: 

Added another --length;  into the if statement below:

                // Is the last thing a quote?
                if ($trim_quote){
                    // Well then get rid of it
                    --$length;
        // ADD TO FIX extra quote
    --$length;
                }
up
-2
robin at teddyb dot org
19 years ago
wchris's quotesplit assumes that anything that is quoted must also be a complete delimiter-seperated entry by itself.  This version does not.  It also uses split's argument order.

    function quotesplit( $splitter=',', $s )
    {
        //First step is to split it up into the bits that are surrounded by quotes
        //and the bits that aren't. Adding the delimiter to the ends simplifies
        //the logic further down

        $getstrings = explode('"', $splitter.$s.$splitter);

        //$instring toggles so we know if we are in a quoted string or not
        $delimlen = strlen($splitter);
        $instring = 0;

        while (list($arg, $val) = each($getstrings))
        {
            if ($instring==1)
            {
                //Add the whole string, untouched to the previous value in the array
                $result[count($result)-1] = $result[count($result)-1].$val;
                $instring = 0;
            }
            else
            {
                //Break up the string according to the delimiter character
                //Each string has extraneous delimiters around it (inc the ones we added
                //above), so they need to be stripped off
                $temparray = split($splitter, substr($val, $delimlen, strlen($val)-$delimlen-$delimlen+1 ) );

                while(list($iarg, $ival) = each($temparray))
                {
                    $result[] = trim($ival);
                }
                $instring = 1;
            }
        }

        return $result;
    }
up
-2
claes at dot2me.com
20 years ago
Though this is obvious, the manual is a bit incorrect when claiming that the return will always be 1+number of time the split pattern occures.  If the split pattern is the first part of the string, the return will still be 1.  E.g.

$a = split("zz," "zzxsj.com");
count($a);

=> 1.

The return of this can not in anyway be seperated from the return where the split pattern is not found.
up
-4
fotw at gmx dot net
22 years ago
Ups! It seems that neither explode nor split REALY takes a STRING but only a single character as a string for splitting the string.
I found this problem in one of my codes when trying to split a string using ";\n" as breaking string. The result, only ";" was thaken... the rest of the string was ignored.
Same when I tried to substitute "\n" by any other thing. :(
up
-3
pascalaschwandenNOSPAM at gmail dot com
16 years ago
The following code will mimick the explode functionality: explode( " ", $s );  The difference, of course, is that the split method takes a regular expression instead of a string.

$s = "Split this sentence by spaces";
$words = split("[ ]+", $s);
print_r($words);

Output:
Array
(
    [0] => Split
    [1] => this
    [2] => sentence
    [3] => by
    [4] => spaces
)
http://www.codesplunk.com/nr/questions/php12.html
up
-4
alphibia at alphibia dot com
20 years ago
I'd like to correct myself, I found that after testing my last solution it will create 5 lines no matter what... So I added this to make sure that it only displays 5 if there are five newlines. :-)

<?php
    $MaxNewLines
= 5;

   
$BRCount = substr_count($Message, '<br />'); 
    if (
$BRCount<$MaxNewLines)
   
$MaxNewLines=$BRCount;
    else if(
$BRCount == 0)
   
$MaxNewLines=1;

   
$Message = str_replace(chr(13), "<br />", $Message);
   
$MessageArray = split("<br />", $Message, $MaxNewLines);
   
$Message = ""; $u=0;
    do    {
   
$Message.=$MessageArray[$u].'<br />';
   
$u++;
    } while(
$u<($MaxNewLines-1));
   
$Message.=str_replace("<br />"," ",$MessageArray[$u]);
   
?>

-Tim
http://www.alphibia.com
up
-5
lewis [ at t] hcoms [d dot t] co [d dot t] uk
16 years ago
Those of you trying to use split for CSV, it won't always work as expected. Instead, try using a simple stack method:

<?php

   
/**
     * Create a 2D array from a CSV string
     *
     * @param mixed $data 2D array
     * @param string $delimiter Field delimiter
     * @param string $enclosure Field enclosure
     * @param string $newline Line seperator
     * @return
     */
   
function parse($data, $delimiter = ',', $enclosure = '"', $newline = "\n"){
       
$pos = $last_pos = -1;
       
$end = strlen($data);
       
$row = 0;
       
$quote_open = false;
       
$trim_quote = false;

       
$return = array();

       
// Create a continuous loop
       
for ($i = -1;; ++$i){
            ++
$pos;
           
// Get the positions
           
$comma_pos = strpos($data, $delimiter, $pos);
           
$quote_pos = strpos($data, $enclosure, $pos);
           
$newline_pos = strpos($data, $newline, $pos);

           
// Which one comes first?
           
$pos = min(($comma_pos === false) ? $end : $comma_pos, ($quote_pos === false) ? $end : $quote_pos, ($newline_pos === false) ? $end : $newline_pos);

           
// Cache it
           
$char = (isset($data[$pos])) ? $data[$pos] : null;
           
$done = ($pos == $end);

           
// It it a special character?
           
if ($done || $char == $delimiter || $char == $newline){

               
// Ignore it as we're still in a quote
               
if ($quote_open && !$done){
                    continue;
                }

               
$length = $pos - ++$last_pos;

               
// Is the last thing a quote?
               
if ($trim_quote){
                   
// Well then get rid of it
                   
--$length;
                }

               
// Get all the contents of this column
               
$return[$row][] = ($length > 0) ? str_replace($enclosure . $enclosure, $enclosure, substr($data, $last_pos, $length)) : '';

               
// And we're done
               
if ($done){
                    break;
                }

               
// Save the last position
               
$last_pos = $pos;

               
// Next row?
               
if ($char == $newline){
                    ++
$row;
                }

               
$trim_quote = false;
            }
           
// Our quote?
           
else if ($char == $enclosure){

               
// Toggle it
               
if ($quote_open == false){
                   
// It's an opening quote
                   
$quote_open = true;
                   
$trim_quote = false;

                   
// Trim this opening quote?
                   
if ($last_pos + 1 == $pos){
                        ++
$last_pos;
                    }

                }
                else {
                   
// It's a closing quote
                   
$quote_open = false;

                   
// Trim the last quote?
                   
$trim_quote = true;
                }

            }

        }

        return
$return;
    }

?>

This *should* work for any valid CSV string, regardless of what it contains inside its quotes (using RFC 4180). It should also be faster than most of the others I've seen. It's very simple in concept, and thoroughly commented.
up
-4
not at anythingspecial dot com
22 years ago
If you need to do a split on a period make sure you escape the period out..

$ext_arr = split("\.","something.jpg");
... because
$ext_arr = split(".","something.jpg"); won't work properly.
up
-6
robin at teddyb dot org
19 years ago
Actually, this version is better than the last I submitted.  The goal here is to be able to engage in *multiple* delimeter removal passes; for all but the last pass, set the third value to "1", and everything should go well.

    function quotesplit( $splitter=',', $s, $restore_quotes=0 )
    {
        //First step is to split it up into the bits that are surrounded by quotes
        //and the bits that aren't. Adding the delimiter to the ends simplifies
        //the logic further down

        $getstrings = explode('"', $splitter.$s.$splitter);

        //$instring toggles so we know if we are in a quoted string or not
        $delimlen = strlen($splitter);
        $instring = 0;

        while (list($arg, $val) = each($getstrings))
        {
            if ($instring==1)
            {
                if( $restore_quotes )
                {
                    //Add the whole string, untouched to the previous value in the array
                    $result[count($result)-1] = $result[count($result)-1].'"'.$val.'"';
                } else {
                    //Add the whole string, untouched to the array
                    $result[] = $val;
                }
                $instring = 0;
            }
            else
            {
                //Break up the string according to the delimiter character
                //Each string has extraneous delimiters around it (inc the ones we added
                //above), so they need to be stripped off
                $temparray = split($splitter, substr($val, $delimlen, strlen($val)-$delimlen-$delimlen+1 ) );

                while(list($iarg, $ival) = each($temparray))
                {
                    $result[] = trim($ival);
                }
                $instring = 1;
            }
        }

        return $result;
    }
up
-5
Mike
17 years ago
// Split a string into words on boundaries of one or more spaces, tabs or new-lines
$s = "Please cut   \t me \n in pieces";
$words = split("[\n\r\t ]+", $s);
print_r($words);

// Output:
Array
(
    [0] => Please
    [1] => cut
    [2] => me
    [3] => in
    [4] => pieces
)
up
-6
Greg Levine
16 years ago
I kept running into the same issue Chris Tyler experienced with lewis [ at t] hcoms [d dot t] co [d dot t] uk's function before realizing that Chris had come up with a solution. However, that solution was just a little off it seems, unless your CSV only contains one line.

If you simply add another --length; in the place you suggested, then the function will always trim the last two characters on the line. Since the newline character is the last character on the line and the redundant quote (or other enclosure) is the second to last character, this works for the final segment. But when parsing segments that do not include a newline character, you end up trimming the redundant enclosure and the last character before the enclosure.

For example,

"he","she","him","her"\r\n

becomes

[0] => h
[1] => sh
[2] => hi
[3] => her

Since the segment could end with the enclosure (i.e., ") or the enclosure followed by the newline (i.e., "\r\n), you have make sure you are only adding another --length; when the latter is the case. Replacing the code block that you suggested with the following will do the trick.

# Is the last thing a newline?
if( $char == $newline )
{
    # Well then get rid of it
    --$length;
}

# Is the last thing a quote?
if( $trim_quote )
{
    # Well then get rid of it
    --$length;
}

I've tested this only for the purposes of the script I'm working on at this time. So, there could be other bugs I haven't come across, but this seems like the easiest way to eliminate the redundant enclosure.
up
-5
kang at elpmis dot com
22 years ago
This is a good way to display a comma delimited file with two columns.  The first column is the URL's description, the second is the actual URL.

<ul>
<?php
  $fname
="relatedlinks.csv";
 
$fp=fopen($fname,"r") or die("Error found.");
 
$line = fgets( $fp, 1024 );
  while(!
feof($fp))
  {
    list(
$desc,$url,$dummy) = split( ",", $line, 3 );
    print
"<li>";
    print
"<a href='$url'>$desc</a>";
    print
"</li>\n";
   
$line = fgets( $fp, 1024 );
  }
 
fclose($fp);
?>
</ul>
To Top