Trabajando con cadenas
Nette\Utils\Strings es una clase estática con funciones útiles para trabajar con cadenas, principalmente en codificación UTF-8.
Instalación:
composer require nette/utils
Todos los ejemplos asumen que se ha creado un alias:
use Nette\Utils\Strings;
Cambiar mayúsculas y minúsculas
Estas funciones requieren la extensión PHP mbstring.
lower (string $s): string
Convierte una cadena UTF-8 a minúsculas.
Strings::lower('Dobrý den'); // 'dobrý den'
upper (string $s): string
Convierte una cadena UTF-8 a mayúsculas.
Strings::upper('Dobrý den'); // 'DOBRÝ DEN'
firstUpper (string $s): string
Convierte la primera letra de una cadena UTF-8 a mayúscula, dejando el resto sin cambios.
Strings::firstUpper('dobrý den'); // 'Dobrý den'
firstLower (string $s): string
Convierte la primera letra de una cadena UTF-8 a minúscula, dejando el resto sin cambios.
Strings::firstLower('Dobrý den'); // 'dobrý den'
capitalize (string $s): string
Convierte la primera letra de cada palabra en una cadena UTF-8 a mayúscula y el resto a minúsculas.
Strings::capitalize('Dobrý den'); // 'Dobrý Den'
Modificar la cadena
normalize (string $s): string
Elimina caracteres de control, normaliza los saltos de línea a \n, elimina las líneas en blanco iniciales y
finales, elimina los espacios finales en las líneas y normaliza UTF-8 a la forma normal NFC.
unixNewLines (string $s): string
Convierte los saltos de línea a \n utilizados en sistemas Unix. Los saltos de línea son: \n,
\r, \r\n, separador de línea U+2028, separador de párrafo U+2029.
$unixLikeLines = Strings::unixNewLines($string);
platformNewLines (string $s): string
Convierte los saltos de línea a los caracteres específicos de la plataforma actual, es decir, \r\n en Windows y
\n en otros sistemas. Los saltos de línea son: \n, \r, \r\n, separador de
línea U+2028, separador de párrafo U+2029.
$platformLines = Strings::platformNewLines($string);
webalize (string $s, ?string $charlist=null, bool $lower=true): string
Modifica una cadena UTF-8 al formato utilizado en las URL, es decir, elimina los diacríticos y reemplaza todos los caracteres, excepto las letras del alfabeto inglés y los números, por guiones.
Strings::webalize('náš produkt'); // 'nas-produkt'
Si se deben conservar otros caracteres, se pueden especificar en el segundo parámetro.
Strings::webalize('10. obrázek_id', '._'); // '10.-obrazek_id'
El tercer parámetro puede desactivar la conversión a minúsculas.
Strings::webalize('Dobrý den', null, false); // 'Dobry-den'
Requiere la extensión PHP intl.
trim (string $s, ?string $charlist=null): string
Elimina espacios (u otros caracteres especificados por el segundo parámetro) del principio y final de una cadena UTF-8.
Strings::trim(' Hello '); // 'Hello'
truncate (string $s, int $maxLen,
string $append=`'…'`): string
Trunca una cadena UTF-8 a la longitud máxima especificada, intentando conservar palabras completas. Si la cadena se acorta, añade puntos suspensivos al final (se puede cambiar mediante el tercer parámetro).
$text = 'Řekněte, jak se máte?';
Strings::truncate($text, 5); // 'Řekn…'
Strings::truncate($text, 20); // 'Řekněte, jak se…'
Strings::truncate($text, 30); // 'Řekněte, jak se máte?'
Strings::truncate($text, 20, '~'); // 'Řekněte, jak se~'
indent (string $s, int $level=1, string
$indentationChar=`"\t"`): string
Indenta un texto multilínea desde la izquierda. El número de indentaciones lo determina el segundo parámetro, y el carácter de indentación el tercero (el valor predeterminado es un tabulador).
Strings::indent('Nette'); // "\tNette"
Strings::indent('Nette', 2, '+'); // '++Nette'
padLeft (string $s, int $length, string
$pad=`' '`): string
Rellena una cadena UTF-8 hasta la longitud especificada repitiendo la cadena $pad por la izquierda.
Strings::padLeft('Nette', 6); // ' Nette'
Strings::padLeft('Nette', 8, '+*'); // '+*+Nette'
padRight (string $s, int $length,
string $pad=`' '`): string
Rellena una cadena UTF-8 hasta la longitud especificada repitiendo la cadena $pad por la derecha.
Strings::padRight('Nette', 6); // 'Nette '
Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
substring (string $s, int $start, ?int $length=null): string
Devuelve una parte de la cadena UTF-8 $s especificada por la posición inicial $start y la longitud
$length. Si $start es negativo, la cadena devuelta comenzará en la posición -$start`
desde el final.
Strings::substring('Nette Framework', 0, 5); // 'Nette'
Strings::substring('Nette Framework', 6); // 'Framework'
Strings::substring('Nette Framework', -4); // 'work'
reverse (string $s): string
Invierte una cadena UTF-8.
Strings::reverse('Nette'); // 'etteN'
length (string $s): int
Devuelve el número de caracteres (no de bytes) en una cadena UTF-8.
Este es el número de puntos de código Unicode, que puede diferir del número de grafemas.
Strings::length('Nette'); // 5
Strings::length('červená'); // 7
startsWith (string $haystack, string $needle): bool
Comprueba si la cadena $haystack empieza por la cadena $needle.
$haystack = 'Začíná';
$needle = 'Za';
Strings::startsWith($haystack, $needle); // true
Utiliza la función nativa str_starts_with().
endsWith (string $haystack, string $needle): bool
Comprueba si la cadena $haystack termina con la cadena $needle.
$haystack = 'Končí';
$needle = 'čí';
Strings::endsWith($haystack, $needle); // true
Utiliza la función nativa str_ends_with().
contains (string $haystack, string $needle): bool
Comprueba si la cadena $haystack contiene la cadena $needle.
$haystack = 'Posluchárna';
$needle = 'sluch';
Strings::contains($haystack, $needle); // true
Utiliza la función nativa str_contains().
compare (string $left, string $right, ?int $length=null): bool
Compara dos cadenas UTF-8 o partes de ellas sin distinguir entre mayúsculas y minúsculas. Si $length es
null, se comparan las cadenas completas; si es negativo, se compara el número correspondiente de caracteres desde el
final de las cadenas; en caso contrario, se compara el número correspondiente de caracteres desde el principio.
Strings::compare('Nette', 'nette'); // true
Strings::compare('Nette', 'next', 2); // true - coincidencia de los primeros 2 caracteres
Strings::compare('Nette', 'Latte', -2); // true - coincidencia de los últimos 2 caracteres
findPrefix (…$strings): string
Encuentra el prefijo común de las cadenas. Devuelve una cadena vacía si no se encuentra un prefijo común.
Strings::findPrefix('prefix-a', 'prefix-bb', 'prefix-c'); // 'prefix-'
Strings::findPrefix(['prefix-a', 'prefix-bb', 'prefix-c']); // 'prefix-'
Strings::findPrefix('Nette', 'is', 'great'); // ''
before (string $haystack, string $needle, int $nth=1): ?string
Devuelve la parte de la cadena $haystack que precede a la n-ésima ($nth) aparición de la cadena
$needle. Devuelve null si no se encuentra $needle. Si $nth es negativo, la
búsqueda se realiza desde el final de la cadena.
Strings::before('Nette_is_great', '_', 1); // 'Nette'
Strings::before('Nette_is_great', '_', -2); // 'Nette'
Strings::before('Nette_is_great', ' '); // null
Strings::before('Nette_is_great', '_', 3); // null
after (string $haystack, string $needle, int $nth=1): ?string
Devuelve la parte de la cadena $haystack que sigue a la n-ésima ($nth) aparición de la cadena
$needle. Devuelve null si no se encuentra $needle. Si $nth es negativo, la
búsqueda se realiza desde el final de la cadena.
Strings::after('Nette_is_great', '_', 2); // 'great'
Strings::after('Nette_is_great', '_', -1); // 'great'
Strings::after('Nette_is_great', ' '); // null
Strings::after('Nette_is_great', '_', 3); // null
indexOf (string $haystack, string $needle, int $nth=1): ?int
Devuelve la posición (en caracteres) de la n-ésima ($nth) aparición de la cadena $needle dentro de
la cadena $haystack. Devuelve null si no se encuentra $needle. Si $nth es
negativo, la búsqueda se realiza desde el final de la cadena.
Strings::indexOf('abc abc abc', 'abc', 2); // 4
Strings::indexOf('abc abc abc', 'abc', -1); // 8
Strings::indexOf('abc abc abc', 'd'); // null
Codificación
fixEncoding (string $s): string
Elimina los caracteres UTF-8 no válidos de la cadena.
$correctStrings = Strings::fixEncoding($string);
checkEncoding (string $s): bool
Comprueba si la cadena es UTF-8 válida.
$isUtf8 = Strings::checkEncoding($string);
Utiliza Nette\Utils\Validator::isUnicode().
toAscii (string $s): string
Convierte una cadena UTF-8 a ASCII, es decir, elimina diacríticos, etc.
Strings::toAscii('žluťoučký kůň'); // 'zlutoucky kun'
Requiere la extensión PHP intl.
chr (int $code): string
Devuelve un carácter específico en UTF-8 a partir de su punto de código (número en el rango 0×0000..D7FF y 0xE000..10FFFF).
Strings::chr(0xA9); // '©' en codificación UTF-8
ord (string $char): int
Devuelve el punto de código de un carácter específico en UTF-8 (número en el rango 0×0000..D7FF o 0xE000..10FFFF).
Strings::ord('©'); // 0xA9
Expresiones regulares
La clase Strings ofrece funciones para trabajar con expresiones regulares. A diferencia de las funciones nativas
de PHP, tienen una API más clara, mejor soporte para Unicode y, sobre todo, detección de errores. Cualquier error durante la
compilación o el procesamiento de la expresión lanza una excepción Nette\RegexpException.
split (string $subject, string $pattern, bool $captureOffset=false, bool $skipEmpty=false, int $limit=-1, bool $utf8=false): array
Divide una cadena en un array utilizando una expresión regular. Las expresiones entre paréntesis también se capturan y devuelven.
Strings::split('hello, world', '~,\s*~');
// ['hello', 'world']
Strings::split('hello, world', '~(,)\s*~');
// ['hello', ',', 'world']``
Si $skipEmpty es true, solo se devuelven los elementos no vacíos:
Strings::split('hello, world, ', '~,\s*~');
// ['hello', 'world', '']
Strings::split('hello, world, ', '~,\s*~', skipEmpty: true);
// ['hello', 'world']
Si se especifica $limit, solo se devuelven subcadenas hasta ese límite, y el resto de la cadena se coloca en el
último elemento. Un límite de –1 o 0 significa que no hay límite.
Strings::split('hello, world, third', '~,\s*~', limit: 2);
// ['hello', 'world, third']
Si $utf8 es true, la evaluación cambia al modo Unicode. Similar a especificar el modificador
u.
Si $captureOffset es true, para cada coincidencia encontrada, también se devolverá su posición en
la cadena (en bytes; o en caracteres si se establece $utf8). Esto cambia el valor devuelto a un array donde cada
elemento es un par formado por la cadena coincidente y su posición.
Strings::split('žlutý, kůň', '~,\s*~', captureOffset: true);
// [['žlutý', 0], ['kůň', 9]]
Strings::split('žlutý, kůň', '~,\s*~', captureOffset: true, utf8: true);
// [['žlutý', 0], ['kůň', 7]]
match (string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $utf8=false): ?array
Busca en una cadena una parte que coincida con una expresión regular y devuelve un array con la expresión encontrada y sus
subexpresiones individuales, o null si no hay coincidencia.
Strings::match('hello!', '~\w+(!+)~');
// ['hello!', '!']
Strings::match('hello!', '~X~');
// null
Si $unmatchedAsNull es true, las subexpresiones no capturadas se devuelven como null; de
lo contrario, se devuelven como una cadena vacía o no se incluyen en el resultado:
Strings::match('hello', '~\w+(!+)?~');
// ['hello']
Strings::match('hello', '~\w+(!+)?~', unmatchedAsNull: true);
// ['hello', null]
Si $utf8 es true, la evaluación cambia al modo Unicode. Similar a especificar el modificador
u:
Strings::match('žlutý kůň', '~\w+~');
// ['lut']
Strings::match('žlutý kůň', '~\w+~', utf8: true);
// ['žlutý']
El parámetro $offset se puede usar para especificar la posición desde la cual comenzar la búsqueda (en bytes;
o en caracteres si se establece $utf8).
Si $captureOffset es true, para cada coincidencia encontrada, también se devolverá su posición en
la cadena (en bytes; o en caracteres si se establece $utf8). Esto cambia el valor devuelto a un array donde cada
elemento es un par formado por la cadena coincidente y su desplazamiento (offset):
Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true);
// [['lut', 2]]
Strings::match('žlutý!', '~\w+(!+)?~', captureOffset: true, utf8: true);
// [['žlutý!', 0], ['!', 5]]
matchAll (string $subject, string $pattern, bool $captureOffset=false, int $offset=0, bool $unmatchedAsNull=false, bool $patternOrder=false, bool $utf8=false, bool $lazy=false): array|Generator
Busca en una cadena todas las ocurrencias que coincidan con una expresión regular y devuelve un array de arrays, cada uno conteniendo la expresión encontrada y sus subexpresiones individuales.
Strings::matchAll('hello, world!!', '~\w+(!+)?~');
/* [
0 => ['hello'],
1 => ['world!!', '!!'],
] */
Si $patternOrder es true, la estructura de los resultados cambia de modo que el primer elemento es un
array de todas las coincidencias completas del patrón, el segundo es un array de las cadenas que coinciden con la primera
subexpresión entre paréntesis, y así sucesivamente:
Strings::matchAll('hello, world!!', '~\w+(!+)?~', patternOrder: true);
/* [
0 => ['hello', 'world!!'],
1 => ['', '!!'],
] */
Si $unmatchedAsNull es true, las subexpresiones no capturadas se devuelven como null; de
lo contrario, se devuelven como una cadena vacía o no se incluyen en el resultado:
Strings::matchAll('hello, world!!', '~\w+(!+)?~', unmatchedAsNull: true);
/* [
0 => ['hello', null],
1 => ['world!!', '!!'],
] */
Si $utf8 es true, la evaluación cambia al modo Unicode. Similar a especificar el modificador
u:
Strings::matchAll('žlutý kůň', '~\w+~');
/* [
0 => ['lut'],
1 => ['k'],
] */
Strings::matchAll('žlutý kůň', '~\w+~', utf8: true);
/* [
0 => ['žlutý'],
1 => ['kůň'],
] */
El parámetro $offset se puede usar para especificar la posición desde la cual comenzar la búsqueda (en bytes;
o en caracteres si se establece $utf8).
Si $captureOffset es true, para cada coincidencia encontrada, también se devolverá su posición en
la cadena (en bytes; o en caracteres si se establece $utf8). Esto cambia el valor devuelto a un array donde cada
elemento es un par formado por la cadena coincidente y su posición:
Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true);
/* [
0 => [['lut', 2]],
1 => [['k', 8]],
] */
Strings::matchAll('žlutý kůň', '~\w+~', captureOffset: true, utf8: true);
/* [
0 => [['žlutý', 0]],
1 => [['kůň', 6]],
] */
Si $lazy es true, la función devuelve un Generator en lugar de un array, lo que ofrece
importantes ventajas de rendimiento al trabajar con cadenas grandes. El generador permite buscar coincidencias de forma
progresiva, en lugar de procesar toda la cadena a la vez. Esto permite trabajar eficientemente incluso con textos de entrada
extremadamente grandes. Además, puedes interrumpir el procesamiento en cualquier momento si encuentras la coincidencia deseada,
lo que ahorra tiempo de cómputo.
$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
foreach ($matches as $match) {
echo "Encontrado: $match[0]\n";
// El procesamiento puede interrumpirse en cualquier momento
}
replace (string $subject, string|array
$pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool
$unmatchedAsNull=false, bool $utf8=false): string
Reemplaza todas las ocurrencias que coinciden con una expresión regular. $replacement es una máscara para la
cadena de reemplazo o una función callback.
Strings::replace('hello, world!', '~\w+~', '--');
// '--, --!'
Strings::replace('hello, world!', '~\w+~', fn($m) => strrev($m[0]));
// 'olleh, dlrow!'
La función también permite realizar múltiples reemplazos pasando un array en el segundo parámetro con el formato
patrón => reemplazo:
Strings::replace('hello, world!', [
'~\w+~' => '--',
'~,\s+~' => ' ',
]);
// '-- --!'
El parámetro $limit limita el número de reemplazos realizados. Un límite de –1 significa que no hay
límite.
Si $utf8 es true, la evaluación cambia al modo Unicode. Similar a especificar el modificador
u.
Strings::replace('žlutý kůň', '~\w+~', '--');
// 'ž--ý --ůň'
Strings::replace('žlutý kůň', '~\w+~', '--', utf8: true);
// '-- --'
Si $captureOffset es true, para cada coincidencia encontrada, también se pasará a la función
callback su posición en la cadena (en bytes; o en caracteres si se establece $utf8). Esto cambia la forma
del array pasado, donde cada elemento es un par formado por la cadena coincidente y su posición.
Strings::replace(
'žlutý kůň',
'~\w+~',
function (array $m) { dump($m); return ''; },
captureOffset: true,
);
// dumps [['lut', 2]] y [['k', 8]]
Strings::replace(
'žlutý kůň',
'~\w+~',
function (array $m) { dump($m); return ''; },
captureOffset: true,
utf8: true,
);
// dumps [['žlutý', 0]] y [['kůň', 6]]
Si $unmatchedAsNull es true, las subexpresiones no capturadas se pasan a la función callback
como null; de lo contrario, se pasan como una cadena vacía o no se incluyen:
Strings::replace(
'ac',
'~(a)(b)*(c)~',
function (array $m) { dump($m); return ''; },
);
// dumps ['ac', 'a', '', 'c']
Strings::replace(
'ac',
'~(a)(b)*(c)~',
function (array $m) { dump($m); return ''; },
unmatchedAsNull: true,
);
// dumps ['ac', 'a', null, 'c']