Trabalhando com strings
Nette\Utils\Strings é uma classe estática com funções úteis para trabalhar com strings, principalmente na codificação UTF-8.
Instalação:
composer require nette/utils
Todos os exemplos assumem que um alias foi criado:
use Nette\Utils\Strings;
Mudança de caixa
Estas funções requerem a extensão PHP mbstring
.
lower (string $s): string
Converte uma string UTF-8 para minúsculas.
Strings::lower('Bom Dia'); // 'bom dia'
upper (string $s): string
Converte uma string UTF-8 para maiúsculas.
Strings::upper('Bom Dia'); // 'BOM DIA'
firstUpper (string $s): string
Converte a primeira letra de uma string UTF-8 para maiúscula, as outras permanecem inalteradas.
Strings::firstUpper('bom dia'); // 'Bom dia'
firstLower (string $s): string
Converte a primeira letra de uma string UTF-8 para minúscula, as outras permanecem inalteradas.
Strings::firstLower('Bom Dia'); // 'bom dia'
capitalize (string $s): string
Converte a primeira letra de cada palavra em uma string UTF-8 para maiúscula, as outras para minúsculas.
Strings::capitalize('Bom Dia'); // 'Bom Dia'
Modificação de string
normalize (string $s): string
Remove caracteres de controle, normaliza as quebras de linha para \n
, remove linhas em branco iniciais e finais,
remove espaços à direita nas linhas, normaliza UTF-8 para a forma normal NFC.
unixNewLines (string $s): string
Converte quebras de linha para \n
usado em sistemas Unix. As quebras de linha são: \n
,
\r
, \r\n
, separador de linha U+2028, separador de parágrafo U+2029.
$unixLikeLines = Strings::unixNewLines($string);
platformNewLines (string $s): string
Converte quebras de linha para caracteres específicos da plataforma atual, ou seja, \r\n
no Windows e
\n
em outros lugares. As quebras de linha são: \n
, \r
, \r\n
, separador de
linha U+2028, separador de parágrafo U+2029.
$platformLines = Strings::platformNewLines($string);
webalize (string $s, ?string $charlist=null, bool $lower=true): string
Modifica uma string UTF-8 para o formato usado em URLs, ou seja, remove diacríticos e substitui todos os caracteres, exceto letras do alfabeto inglês e números, por hífens.
Strings::webalize('nosso produto'); // 'nosso-produto'
Se outros caracteres devem ser preservados, eles podem ser listados no segundo parâmetro da função.
Strings::webalize('10. imagem_id', '._'); // '10.-imagem_id'
O terceiro parâmetro pode suprimir a conversão para minúsculas.
Strings::webalize('Bom Dia', null, false); // 'Bom-Dia'
Requer a extensão PHP intl
.
trim (string $s, ?string $charlist=null): string
Remove espaços (ou outros caracteres especificados pelo segundo parâmetro) do início e do fim de uma string UTF-8.
Strings::trim(' Olá '); // 'Olá'
truncate (string $s, int $maxLen,
string $append=`'…'
`): string
Trunca uma string UTF-8 para o comprimento máximo especificado, tentando preservar palavras inteiras. Se a string for encurtada, adiciona reticências no final (pode ser alterado com o terceiro parâmetro).
$text = 'Diga-me, como você está?';
Strings::truncate($text, 5); // 'Diga…'
Strings::truncate($text, 20); // 'Diga-me, como você…'
Strings::truncate($text, 30); // 'Diga-me, como você está?'
Strings::truncate($text, 20, '~'); // 'Diga-me, como você~'
indent (string $s, int $level=1, string
$indentationChar=`"\t"
`): string
Indenta um texto de várias linhas pela esquerda. O número de indentações é determinado pelo segundo parâmetro, o caractere de indentação pelo terceiro (o valor padrão é tabulação).
Strings::indent('Nette'); // "\tNette"
Strings::indent('Nette', 2, '+'); // '++Nette'
padLeft (string $s, int $length, string
$pad=`' '
`): string
Preenche uma string UTF-8 até o comprimento especificado repetindo a string $pad
pela esquerda.
Strings::padLeft('Nette', 6); // ' Nette'
Strings::padLeft('Nette', 8, '+*'); // '+*+Nette'
padRight (string $s, int $length,
string $pad=`' '
`): string
Preenche uma string UTF-8 até o comprimento especificado repetindo a string $pad
pela direita.
Strings::padRight('Nette', 6); // 'Nette '
Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'
substring (string $s, int $start, ?int $length=null): string
Retorna uma parte da string UTF-8 $s
especificada pela posição inicial $start
e comprimento
$length
. Se $start
for negativo, a string retornada começará no caractere -$start
a
partir do final.
Strings::substring('Nette Framework', 0, 5); // 'Nette'
Strings::substring('Nette Framework', 6); // 'Framework'
Strings::substring('Nette Framework', -4); // 'work'
reverse (string $s): string
Inverte uma string UTF-8.
Strings::reverse('Nette'); // 'etteN'
length (string $s): int
Retorna o número de caracteres (não bytes) em uma string UTF-8.
Este é o número de pontos de código Unicode, que pode diferir do número de grafemas.
Strings::length('Nette'); // 5
Strings::length('červená'); // 7
startsWith (string $haystack, string $needle): bool
Verifica se a string $haystack
começa com a string $needle
.
$haystack = 'Começa';
$needle = 'Co';
Strings::startsWith($haystack, $needle); // true
Use a função nativa str_starts_with()
.
endsWith (string $haystack, string $needle): bool
Verifica se a string $haystack
termina com a string $needle
.
$haystack = 'Termina';
$needle = 'ina';
Strings::endsWith($haystack, $needle); // true
Use a função nativa str_ends_with()
.
contains (string $haystack, string $needle): bool
Verifica se a string $haystack
contém $needle
.
$haystack = 'Auditório';
$needle = 'dit';
Strings::contains($haystack, $needle); // true
Use a função nativa str_contains()
.
compare (string $left, string $right, ?int $length=null): bool
Compara duas strings UTF-8 ou suas partes, ignorando maiúsculas e minúsculas. Se $length
for null, as strings
inteiras são comparadas; se for negativo, o número correspondente de caracteres do final das strings é comparado; caso
contrário, o número correspondente de caracteres do início é comparado.
Strings::compare('Nette', 'nette'); // true
Strings::compare('Nette', 'next', 2); // true - correspondência dos primeiros 2 caracteres
Strings::compare('Nette', 'Latte', -2); // true - correspondência dos últimos 2 caracteres
findPrefix (…$strings): string
Encontra o prefixo comum das strings. Ou retorna uma string vazia se nenhum prefixo comum for encontrado.
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
Retorna a parte da string $haystack
antes da n-ésima ocorrência $nth
da string
$needle
. Ou null
se $needle
não for encontrado. Com um valor negativo para
$nth
, a busca é feita a partir do final da string.
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
Retorna a parte da string $haystack
após a n-ésima ocorrência $nth
da string $needle
.
Ou null
se $needle
não for encontrado. Com um valor negativo para $nth
, a busca é feita a
partir do final da string.
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
Retorna a posição em caracteres da n-ésima ocorrência $nth
da string $needle
na string
$haystack
. Ou null
se $needle
não for encontrado. Com um valor negativo para
$nth
, a busca é feita a partir do final da string.
Strings::indexOf('abc abc abc', 'abc', 2); // 4
Strings::indexOf('abc abc abc', 'abc', -1); // 8
Strings::indexOf('abc abc abc', 'd'); // null
Codificação
fixEncoding (string $s): string
Remove caracteres UTF-8 inválidos da string.
$correctStrings = Strings::fixEncoding($string);
checkEncoding (string $s): bool
Verifica se é uma string UTF-8 válida.
$isUtf8 = Strings::checkEncoding($string);
Use Nette\Utils\Validator::isUnicode().
toAscii (string $s): string
Converte uma string UTF-8 para ASCII, ou seja, remove diacríticos, etc.
Strings::toAscii('žluťoučký kůň'); // 'zlutoucky kun'
Requer a extensão PHP intl
.
chr (int $code): string
Retorna um caractere específico em UTF-8 a partir do ponto de código (número no intervalo 0×0000..D7FF e 0xE000..10FFFF).
Strings::chr(0xA9); // '©' na codificação UTF-8
ord (string $char): int
Retorna o ponto de código de um caractere específico em UTF-8 (número no intervalo 0×0000..D7FF ou 0xE000..10FFFF).
Strings::ord('©'); // 0xA9
Expressões Regulares
A classe Strings oferece funções para trabalhar com expressões regulares. Ao contrário das funções nativas do PHP, elas
possuem uma API mais compreensível, melhor suporte a Unicode e, acima de tudo, detecção de erros. Qualquer erro durante a
compilação ou processamento da expressão lançará uma exceção Nette\RegexpException
.
split (string $subject, string $pattern, bool $captureOffset=false, bool $skipEmpty=false, int $limit=-1, bool $utf8=false): array
Divide uma string em um array usando uma expressão regular. Expressões entre parênteses também serão capturadas e retornadas.
Strings::split('hello, world', '~,\s*~');
// ['hello', 'world']
Strings::split('hello, world', '~(,)\s*~');
// ['hello', ',', 'world']``
Se $skipEmpty
for true
, apenas itens não vazios serão retornados:
Strings::split('hello, world, ', '~,\s*~');
// ['hello', 'world', '']
Strings::split('hello, world, ', '~,\s*~', skipEmpty: true);
// ['hello', 'world']
Se $limit
for especificado, apenas substrings até o limite serão retornadas, e o restante da string será
colocado no último elemento. Um limite de –1 ou 0 significa sem limite.
Strings::split('hello, world, third', '~,\s*~', limit: 2);
// ['hello', 'world, third']
Se $utf8
for true
, a avaliação muda para o modo Unicode. Semelhante a especificar o modificador
u
.
Se $captureOffset
for true
, para cada correspondência encontrada, sua posição na string (em bytes;
se $utf8
estiver definido, em caracteres) também será retornada. Isso altera o valor de retorno para um array onde
cada elemento é um par composto pela string correspondente e sua posição.
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
Procura na string uma parte que corresponda à expressão regular e retorna um array com a expressão encontrada e
subexpressões individuais, ou null
.
Strings::match('hello!', '~\w+(!+)~');
// ['hello!', '!']
Strings::match('hello!', '~X~');
// null
Se $unmatchedAsNull
for true
, subpadrões não capturados são retornados como null; caso contrário,
são retornados como uma string vazia ou não são retornados:
Strings::match('hello', '~\w+(!+)?~');
// ['hello']
Strings::match('hello', '~\w+(!+)?~', unmatchedAsNull: true);
// ['hello', null]
Se $utf8
for true
, a avaliação muda para o modo Unicode. Semelhante a especificar o modificador
u
:
Strings::match('žlutý kůň', '~\w+~');
// ['lut']
Strings::match('žlutý kůň', '~\w+~', utf8: true);
// ['žlutý']
O parâmetro $offset
pode ser usado para especificar a posição a partir da qual a busca deve começar (em
bytes; se $utf8
estiver definido, em caracteres).
Se $captureOffset
for true
, para cada correspondência encontrada, sua posição na string (em bytes;
se $utf8
estiver definido, em caracteres) também será retornada. Isso altera o valor de retorno para um array onde
cada elemento é um par composto pela string correspondente e seu 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
Procura na string todas as ocorrências que correspondem à expressão regular e retorna um array de arrays com a expressão encontrada e subexpressões individuais.
Strings::matchAll('hello, world!!', '~\w+(!+)?~');
/* [
0 => ['hello'],
1 => ['world!!', '!!'],
] */
Se $patternOrder
for true
, a estrutura dos resultados muda de forma que o primeiro item é um array
de correspondências completas do padrão, o segundo é um array de strings correspondentes ao primeiro subpadrão entre
parênteses, e assim por diante:
Strings::matchAll('hello, world!!', '~\w+(!+)?~', patternOrder: true);
/* [
0 => ['hello', 'world!!'],
1 => ['', '!!'],
] */
Se $unmatchedAsNull
for true
, subpadrões não capturados são retornados como null; caso contrário,
são retornados como uma string vazia ou não são retornados:
Strings::matchAll('hello, world!!', '~\w+(!+)?~', unmatchedAsNull: true);
/* [
0 => ['hello', null],
1 => ['world!!', '!!'],
] */
Se $utf8
for true
, a avaliação muda para o modo Unicode. Semelhante a especificar o modificador
u
:
Strings::matchAll('žlutý kůň', '~\w+~');
/* [
0 => ['lut'],
1 => ['k'],
] */
Strings::matchAll('žlutý kůň', '~\w+~', utf8: true);
/* [
0 => ['žlutý'],
1 => ['kůň'],
] */
O parâmetro $offset
pode ser usado para especificar a posição a partir da qual a busca deve começar (em
bytes; se $utf8
estiver definido, em caracteres).
Se $captureOffset
for true
, para cada correspondência encontrada, sua posição na string (em bytes;
se $utf8
estiver definido, em caracteres) também será retornada. Isso altera o valor de retorno para um array onde
cada elemento é um par composto pela string correspondente e sua posição:
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]],
] */
Se $lazy
for true
, a função retorna um Generator
em vez de um array, o que traz
vantagens significativas de desempenho ao trabalhar com strings grandes. O gerador permite buscar correspondências gradualmente,
em vez de toda a string de uma vez. Isso permite trabalhar eficientemente mesmo com textos de entrada extremamente grandes. Além
disso, você pode interromper o processamento a qualquer momento se encontrar a correspondência desejada, economizando tempo de
computação.
$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
foreach ($matches as $match) {
echo "Encontrado: $match[0]\n";
// O processamento pode ser interrompido a qualquer momento
}
replace (string $subject, string|array
$pattern, string|callable $replacement=''
, int $limit=-1, bool $captureOffset=false, bool
$unmatchedAsNull=false, bool $utf8=false): string
Substitui todas as ocorrências que correspondem à expressão regular. $replacement
é uma máscara de string de
substituição ou um callback.
Strings::replace('hello, world!', '~\w+~', '--');
// '--, --!'
Strings::replace('hello, world!', '~\w+~', fn($m) => strrev($m[0]));
// 'olleh, dlrow!'
A função também permite realizar múltiplas substituições passando um array no segundo parâmetro no formato
pattern => replacement
:
Strings::replace('hello, world!', [
'~\w+~' => '--',
'~,\s+~' => ' ',
]);
// '-- --!'
O parâmetro $limit
restringe o número de substituições realizadas. Um limite de –1 significa sem
limite.
Se $utf8
for true
, a avaliação muda para o modo Unicode. Semelhante a especificar o modificador
u
.
Strings::replace('žlutý kůň', '~\w+~', '--');
// 'ž--ý --ůň'
Strings::replace('žlutý kůň', '~\w+~', '--', utf8: true);
// '-- --'
Se $captureOffset
for true
, para cada correspondência encontrada, sua posição na string (em bytes;
se $utf8
estiver definido, em caracteres) também será passada para o callback. Isso altera a forma do array
passado, onde cada elemento é um par composto pela string correspondente e sua posição.
Strings::replace(
'žlutý kůň',
'~\w+~',
function (array $m) { dump($m); return ''; },
captureOffset: true,
);
// dumps [['lut', 2]] e [['k', 8]]
Strings::replace(
'žlutý kůň',
'~\w+~',
function (array $m) { dump($m); return ''; },
captureOffset: true,
utf8: true,
);
// dumps [['žlutý', 0]] e [['kůň', 6]]
Se $unmatchedAsNull
for true
, subpadrões não capturados são passados para o callback como null;
caso contrário, são passados como uma string vazia ou não são passados:
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']