ConFoo: Call for paper is now Open

preg_split

(PHP 4, PHP 5)

preg_splitDivide un string mediante una expresión regular

Descripción

array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] )

Divide el string dado mediante una expresión regular.

Parámetros

pattern

El patrón de búsqueda, dado como string.

subject

El string de entrada.

limit

Si se especifica, son devueltos sólo los substrings hasta limit, con el resto del string colocado en el último substring. Si limit vale -1, 0 o NULL, significa "sin límite" y, como es un estándar en PHP, se puede usar NULL para saltar hacia el parámetro flags.

flags

flags puede ser una combinación de las siguientes banderas (combinadas con el operador | a nivel de bits):

PREG_SPLIT_NO_EMPTY
Si se aplica esta bandera, sólo los elementos no vacíos serán devueltos por preg_split().
PREG_SPLIT_DELIM_CAPTURE
Si se aplica esta bandera, las expresiones entre paréntesis en el patrón delimitador serán capturadas y devueltas.
PREG_SPLIT_OFFSET_CAPTURE

Si se aplica esta bandera, por cada coincidencia producida, el índice del string añadido también será devuelto. Observe que esto cambia el valor devuelto dentro de un array donde cada elemento es un array consistente en el string coincidente en el índice 0 y su índice de string dentro de subject en el índice 1.

Valores devueltos

Devuelve un array que contiene substrings de subject dividido por los límites coincidentes de pattern.

Ejemplos

Ejemplo #1 Ejemplo de preg_split() : Obtener las partes de un string de búsqueda

<?php
// divide la frase mediante cualquier número de comas o caracteres de espacio,
// lo que incluye " ", \r, \t, \n y \f
$claves preg_split("/[\s,]+/""hypertext language, programming");
print_r($claves);
?>

El resultado del ejemplo sería:

Array
(
    [0] => hypertext
    [1] => language
    [2] => programming
)

Ejemplo #2 Dividir un string en sus caracteres constituyentes

<?php
$str 
'string';
$caracteres preg_split('//'$str, -1PREG_SPLIT_NO_EMPTY);
print_r($caracteres);
?>

El resultado del ejemplo sería:

Array
(
    [0] => s
    [1] => t
    [2] => r
    [3] => i
    [4] => n
    [5] => g
)

Ejemplo #3 Dividir un string mediante coincidencias y sus índices

<?php
$str 
'hypertext language programming';
$caracteres preg_split('/ /'$str, -1PREG_SPLIT_OFFSET_CAPTURE);
print_r($caracteres);
?>

El resultado del ejemplo sería:

Array
(
    [0] => Array
        (
            [0] => hypertext
            [1] => 0
        )

    [1] => Array
        (
            [0] => language
            [1] => 10
        )

    [2] => Array
        (
            [0] => programming
            [1] => 19
        )

)

Notas

Sugerencia

Si no necesita la potencia de expresiones regulares, puede optar por alternativas más rápidas (no obstante más sencillas) como explode() o str_split().

Sugerencia

Si la comparación falla, será devuelto un array con un único elemento que contiene el string de entrada.

Ver también

add a note add a note

User Contributed Notes 18 notes

up
11
jan dot sochor at icebolt dot info
4 years ago
Sometimes PREG_SPLIT_DELIM_CAPTURE does strange results.

<?php
$content
= '<strong>Lorem ipsum dolor</strong> sit <img src="test.png" />amet <span class="test" style="color:red">consec<i>tet</i>uer</span>.';
$chars = preg_split('/<[^>]*[^\/]>/i', $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
print_r($chars);
?>
Produces:
Array
(
    [0] => Lorem ipsum dolor
    [1] =>  sit <img src="test.png" />amet
    [2] => consec
    [3] => tet
    [4] => uer
)

So that the delimiter patterns are missing. If you wanna get these patters remember to use parentheses.

<?php
$chars
= preg_split('/(<[^>]*[^\/]>)/i', $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
print_r($chars); //parentheses added
?>
Produces:
Array
(
    [0] => <strong>
    [1] => Lorem ipsum dolor
    [2] => </strong>
    [3] =>  sit <img src="test.png" />amet
    [4] => <span class="test" style="color:red">
    [5] => consec
    [6] => <i>
    [7] => tet
    [8] => </i>
    [9] => uer
    [10] => </span>
    [11] => .
)
up
6
jetsoft at iinet.net.au
9 years ago
To clarify the "limit" parameter and the PREG_SPLIT_DELIM_CAPTURE option,

<?php
$preg_split
('(/ /)', '1 2 3 4 5 6 7 8', 4 ,PREG_SPLIT_DELIM_CAPTURE );
?>

returns:

('1', ' ', '2', ' ' , '3', ' ', '4 5 6 7 8')

So you actually get 7 array items not 4
up
4
Daniel Schroeder
3 years ago
If you want to split by a char, but want to ignore that char in case it is escaped, use a lookbehind assertion.

In this example a string will be split by ":" but "\:" will be ignored:

<?php
$string
='a:b:c\:d';
$array=preg_split('#(?<!\\\)\:#',$string);
print_r($array);
?>

Results into:

Array
(
    [0] => a
    [1] => b
    [2] => c\:d
)
up
4
wf
5 years ago
Spacing out your CamelCase using preg_replace:

<?php

function spacify($camel, $glue = ' ') {
    return
preg_replace( '/([a-z0-9])([A-Z])/', "$1$glue$2", $camel );
}

echo
spacify('CamelCaseWords'), "\n"; // 'Camel Case Words'
echo spacify('camelCaseWords'), "\n"; // 'camel Case Words'

?>
up
2
nesbert at gmail dot com
4 years ago
Hope this helps someone...

<?php
/**
* Split a string into groups of words with a line no longer than $max
* characters.
*
* @param string $string
* @param integer $max
* @return array
**/
function split_words($string, $max = 1)
{
   
$words = preg_split('/\s/', $string);
   
$lines = array();
   
$line = '';
   
    foreach (
$words as $k => $word) {
       
$length = strlen($line . ' ' . $word);
        if (
$length <= $max) {
           
$line .= ' ' . $word;
        } else if (
$length > $max) {
            if (!empty(
$line)) $lines[] = trim($line);
           
$line = $word;
        } else {
           
$lines[] = trim($line) . ' ' . $word;
           
$line = '';
        }
    }
   
$lines[] = ($line = trim($line)) ? $line : $word;

    return
$lines;
}
?>
up
3
buzoganylaszlo at yahoo dot com
5 years ago
Extending m.timmermans's solution, you can use the following code as a search expression parser:

<?php
$search_expression
= "apple bear \"Tom Cruise\" or 'Mickey Mouse' another word";
$words = preg_split("/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|" . "[\s,]*'([^']+)'[\s,]*|" . "[\s,]+/", $search_expression, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
print_r($words);
?>

The result will be:
Array
(
    [0] => apple
    [1] => bear
    [2] => Tom Cruise
    [3] => or
    [4] => Mickey Mouse
    [5] => another
    [6] => word
)

1. Accepted delimiters: white spaces (space, tab, new line etc.) and commas.

2. You can use either simple (') or double (") quotes for expressions which contains more than one word.
up
3
eric at clarinova dot com
3 years ago
Here is another way to split a CamelCase string, which is a simpler expression than the one using lookaheads and lookbehinds:

preg_split('/([[:upper:]][[:lower:]]+)/', $last, null, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY)

It makes the entire CamelCased word the delimiter, then returns the delimiters (PREG_SPLIT_DELIM_CAPTURE) and omits the empty values between the delimiters (PREG_SPLIT_NO_EMPTY)
up
1
php at dmi dot me dot uk
4 years ago
To split a camel-cased string using preg_split() with lookaheads and lookbehinds:

<?php
function splitCamelCase($str) {
  return
preg_split('/(?<=\\w)(?=[A-Z])/', $str);
}
?>
up
1
Peter -the pete- de Pijd
4 years ago
If you want to use something like explode(PHP_EOL, $string) but for all combinations of \r and \n, try this one:

<?php
$text
= "A\nB\rC\r\nD\r\rE\n\nF";
$texts = preg_split("/((\r(?!\n))|((?<!\r)\n)|(\r\n))/", $text);
?>

result:
array("A", "B", "C", "D", "", "E", "", "F");
up
2
PhoneixSegovia at gmail dot com
3 years ago
You must be caution when using lookbehind to a variable match.
For example:
'/(?<!\\\)\r?\n)/'
to match a new line when not \ is before it don't go as spected as it match \r as the lookbehind (becouse isn't a \) and is optional before \n.

You must use this for example:
'/((?<!\\\|\r)\n)|((?<!\\\)\r\n)/'
That match a alone \n (not preceded by \r or \) or a \r\n not preceded by a \.
up
1
csaba at alum dot mit dot edu
5 years ago
If the task is too complicated for preg_split, preg_match_all might come in handy, since preg_split is essentially a special case.

I wanted to split a string on a certain character (asterisk), but only if it wasn't escaped (by a preceding backslash).  Thus, I should ensure an even number of backslashes before any asterisk meant as a splitter.  Look-behind in a regular expression wouldn't work since the length of the preceding backslash sequence can't be fixed.  So I turned to preg_match_all:

<?php
// split a string at unescaped asterisks
// where backslash is the escape character
$splitter = "/\\*((?:[^\\\\*]|\\\\.)*)/";
preg_match_all($splitter, "*$string", $aPieces, PREG_PATTERN_ORDER);
$aPieces = $aPieces[1];

// $aPieces now contains the exploded string
// and unescaping can be safely done on each piece
foreach ($aPieces as $idx=>$piece)
 
$aPieces[$idx] = preg_replace("/\\\\(.)/s", "$1", $piece);
?>
up
0
Miller
6 months ago
This is a function to truncate a string of text while preserving the whitespace (for instance, getting an excerpt from an article while maintaining newlines). It will not jive well with HTML, of course.

<?php
/**
* Truncates a string of text by word count
* @param string $text The text to truncate
* @param int $max_words The maximum number of words
* @return string The truncated text
*/
function limit_words ($text, $max_words) {
   
$split = preg_split('/(\s+)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
   
$truncated = '';
    for (
$i = 0; $i < min(count($split), $max_words*2); $i += 2) {
       
$truncated .= $split[$i].$split[$i+1];
    }
    return
trim($truncated);
}
?>
up
0
kenorb at gmail dot com
5 years ago
If you need convert function arguments without default default values and references, you can try this code:

<?php
    $func_args
= '$node, $op, $a3 = NULL, $form = array(), $a4 = NULL'
   
$call_arg = preg_match_all('@(?<func_arg>\$[^,= ]+)@i', $func_args, $matches);
   
$call_arg = implode(',', $matches['func_arg']);
?>
Result: string = "$node,$op,$a3,$form,$a4"
up
0
anajilly
6 years ago
<?php
$s
= '<p>bleh blah</p><p style="one">one two three</p>';

$htmlbits = preg_split('/(<p( style="[-:a-z0-9 ]+")?>|<\/p>)/i', $s, -1, PREG_SPLIT_DELIM_CAPTURE);

print_r($htmlbits);
?>

Array
(
    [0] =>
    [1] => <p>
    [2] => bleh blah
    [3] => </p>
    [4] =>
    [5] => <p style="one">
    [6] =>  style="one"
    [7] => one two three
    [8] => </p>
    [9] =>
)

two interesting bits:

1. When using PREG_SPLIT_DELIM_CAPTURE, if you use more than one pair of parentheses, the result array can have members representing all pairs.  See array indexes 5 and 6 to see two adjacent delimiter results in which the second is a subset match of the first.

2. If a parenthesised sub-expression is made optional by a following question mark (ex: '/abc (optional subregex)?/') some split delimiters may be captured in the result while others are not.  See array indexes 1 and 2 to see an instance where the overall match succeeded and returned a delimiter while the optional sub-expression '( style="[-:a-z0-9 ]+")?' did not match, and did not return a delimiter.  This means it's possible to have a result with an unpredictable number of delimiters in the result array.

This second aspect is true irrespective of the number of pairs of parentheses in the regex.  This means: in a regular expression with a single optional parenthesised sub-expression, the overall expression can match without generating a corresponding delimiter in the result.
up
0
Steve
9 years ago
preg_split() behaves differently from perl's split() if the string ends with a delimiter. This perl snippet will print 5:

my @a = split(/ /, "a b c d e ");
print scalar @a;

The corresponding php code prints 6:

<?php print count(preg_split("/ /", "a b c d e ")); ?>

This is not necessarily a bug (nowhere does the documentation say that preg_split() behaves the same as perl's split()) but it might surprise perl programmers.
up
-1
w o z 2 2 a t y a h o o d o t c o m
3 years ago
PREG_SPLIT_OFFSET_CAPTURE should be maintained for UTF-8 characters, because it produces wrong results as if it is using strlen() internally, instead of using mb_strlen(), which is the right one...
up
-1
david dot binovec at gmail dot com
3 years ago
Limit = 1 may be confusing. The important thing is that in case of limit equals to 1 will produce only ONE substring. Ergo the only one substring will be the first one as well as the last one. Tnat the rest of the string (after the first delimiter) will be placed to the last substring. But last is the first and only one.

<?php

$output
= $preg_split('(/ /)', '1 2 3 4 5 6 7 8', 1);

echo
$output[0] //will return whole string!;

$output = $preg_split('(/ /)', '1 2 3 4 5 6 7 8', 2);

echo
$output[0] //will return 1;
echo $output[1] //will return '2 3 4 5 6 7 8';

?>
up
-3
anton at zebooka dot com
1 year ago
A not good code in example regexp.
It should be written
preg_split("/[\\s,]+", ...
because there is no special symbol \s (like \n for example) and we need to pass exactly \s, not symbol that \s may represent.
So we need to escape backslash with backslash

$a = "/[\\s,+]/";
echo $a;
php> /[\s,+]/
To Top