文字列の操作

Nette\Utils\Strings は、主にUTF-8エンコーディングの文字列を操作するための便利な関数を持つ静的クラスです。

インストール:

composer require nette/utils

すべての例は、エイリアスが作成されていることを前提としています:

use Nette\Utils\Strings;

大文字小文字の変更

これらの関数にはPHP拡張機能 mbstring が必要です。

lower (string $s): string

UTF-8文字列を小文字に変換します。

Strings::lower('Dobrý den'); // 'dobrý den'

upper (string $s): string

UTF-8文字列を大文字に変換します。

Strings::upper('Dobrý den'); // 'DOBRÝ DEN'

firstUpper (string $s): string

UTF-8文字列の最初の文字を大文字に変換し、残りは変更しません。

Strings::firstUpper('dobrý den'); // 'Dobrý den'

firstLower (string $s): string

UTF-8文字列の最初の文字を小文字に変換し、残りは変更しません。

Strings::firstLower('Dobrý den'); // 'dobrý den'

capitalize (string $s): string

UTF-8文字列の各単語の最初の文字を大文字に変換し、残りを小文字に変換します。

Strings::capitalize('Dobrý den'); // 'Dobrý Den'

文字列の編集

normalize (string $s): string

制御文字を削除し、改行を \n に正規化し、先頭と末尾の空行をトリムし、行末の右側のスペースをトリムし、UTF-8を正規形式NFCに正規化します。

unixNewLines (string $s): string

改行をUnixシステムで使用される \n に変換します。改行は \n\r\r\n、U+2028 行区切り文字、U+2029 段落区切り文字です。

$unixLikeLines = Strings::unixNewLines($string);

platformNewLines (string $s)string

改行を現在のプラットフォーム固有の文字に変換します。つまり、Windowsでは \r\n、その他では \n です。改行は \n\r\r\n、U+2028 行区切り文字、U+2029 段落区切り文字です。

$platformLines = Strings::platformNewLines($string);

webalize (string $s, ?string $charlist=null, bool $lower=true)string

UTF-8文字列をURLで使用される形式に編集します。つまり、発音区別符号を削除し、英字と数字以外のすべての文字をハイフンに置き換えます。

Strings::webalize('náš produkt'); // 'nas-produkt'

他の文字も保持したい場合は、関数の2番目のパラメータで指定できます。

Strings::webalize('10. obrázek_id', '._'); // '10.-obrazek_id'

3番目のパラメータで小文字への変換を抑制できます。

Strings::webalize('Dobrý den', null, false); // 'Dobry-den'

PHP拡張機能 intl が必要です。

trim (string $s, ?string $charlist=null)string

UTF-8文字列の先頭と末尾から空白(または2番目のパラメータで指定された他の文字)をトリムします。

Strings::trim('  Hello  '); // 'Hello'

truncate (string $s, int $maxLen, string $append=`'…'`)string

UTF-8文字列を指定された最大長に切り詰めますが、単語全体を保持しようとします。文字列が短縮された場合、末尾に三点リーダーを追加します(3番目のパラメータで変更可能)。

$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

複数行テキストを左からインデントします。インデントの数は2番目のパラメータで、インデントに使用する文字は3番目のパラメータで指定します(デフォルト値はタブ)。

Strings::indent('Nette');         // "\tNette"
Strings::indent('Nette', 2, '+'); // '++Nette'

padLeft (string $s, int $length, string $pad=`' '`)string

UTF-8文字列を、左から文字列 $pad を繰り返して指定された長さに補完します。

Strings::padLeft('Nette', 6);        // ' Nette'
Strings::padLeft('Nette', 8, '+*');  // '+*+Nette'

padRight (string $s, int $length, string $pad=`' '`)string

UTF-8文字列を、右から文字列 $pad を繰り返して指定された長さに補完します。

Strings::padRight('Nette', 6);       // 'Nette '
Strings::padRight('Nette', 8, '+*'); // 'Nette+*+'

substring (string $s, int $start, ?int $length=null)string

UTF-8文字列 $s の一部を、開始位置 $start と長さ $length で指定して返します。$start が負の場合、返される文字列は末尾から -$start` 番目の文字から始まります。

Strings::substring('Nette Framework', 0, 5); // 'Nette'
Strings::substring('Nette Framework', 6);    // 'Framework'
Strings::substring('Nette Framework', -4);   // 'work'

reverse (string $s): string

UTF-8文字列を反転します。

Strings::reverse('Nette'); // 'etteN'

length (string $s): int

UTF-8文字列の文字数(バイト数ではない)を返します。

これはUnicodeコードポイントの数であり、書記素の数とは異なる場合があります。

Strings::length('Nette');   // 5
Strings::length('červená'); // 7

startsWith (string $haystack, string $needle)bool

文字列 $haystack が文字列 $needle で始まるかどうかを調べます。

$haystack = 'Začíná';
$needle = 'Za';
Strings::startsWith($haystack, $needle); // true

ネイティブの str_starts_with() を使用してください。

endsWith (string $haystack, string $needle)bool

文字列 $haystack が文字列 $needle で終わるかどうかを調べます。

$haystack = 'Končí';
$needle = 'čí';
Strings::endsWith($haystack, $needle); // true

ネイティブの str_ends_with() を使用してください。

contains (string $haystack, string $needle)bool

文字列 $haystack$needle を含むかどうかを調べます。

$haystack = 'Posluchárna';
$needle = 'sluch';
Strings::contains($haystack, $needle); // true

ネイティブの str_contains() を使用してください。

compare (string $left, string $right, ?int $length=null)bool

2つのUTF-8文字列またはその一部を、大文字小文字を区別せずに比較します。$length がnullの場合、文字列全体が比較されます。負の場合、文字列の末尾から対応する文字数が比較されます。それ以外の場合、文字列の先頭から対応する文字数が比較されます。

Strings::compare('Nette', 'nette');     // true
Strings::compare('Nette', 'next', 2);   // true - 最初の2文字が一致
Strings::compare('Nette', 'Latte', -2); // true - 最後の2文字が一致

findPrefix (…$strings): string

文字列の共通の接頭辞を見つけます。共通の接頭辞が見つからない場合は空の文字列を返します。

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

文字列 $haystack の中で、文字列 $needle のn番目($nth)の出現箇所の前の部分を返します。$needle が見つからない場合は null を返します。$nth が負の値の場合、文字列の末尾から検索します。

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

文字列 $haystack の中で、文字列 $needle のn番目($nth)の出現箇所の後の部分を返します。$needle が見つからない場合は null を返します。$nth が負の値の場合、文字列の末尾から検索します。

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

文字列 $haystack 内の文字列 $needle のn番目($nth)の出現位置を文字数で返します。$needle が見つからない場合は null を返します。$nth が負の値の場合、文字列の末尾から検索します。

Strings::indexOf('abc abc abc', 'abc', 2);  // 4
Strings::indexOf('abc abc abc', 'abc', -1); // 8
Strings::indexOf('abc abc abc', 'd');       // null

エンコーディング

fixEncoding (string $s): string

文字列から無効なUTF-8文字を削除します。

$correctStrings = Strings::fixEncoding($string);

checkEncoding (string $s)bool

有効なUTF-8文字列かどうかを調べます。

$isUtf8 = Strings::checkEncoding($string);

Nette\Utils\Validator::isUnicode() を使用してください。

toAscii (string $s): string

UTF-8文字列をASCIIに変換します。つまり、発音区別符号などを削除します。

Strings::toAscii('žluťoučký kůň'); // 'zlutoucky kun'

PHP拡張機能 intl が必要です。

chr (int $code): string

コードポイント(0×0000..D7FFおよび0xE000..10FFFFの範囲の数値)から特定のUTF-8文字を返します。

Strings::chr(0xA9); // UTF-8エンコーディングの '©'

ord (string $char): int

特定のUTF-8文字のコードポイント(0×0000..D7FFまたは0xE000..10FFFFの範囲の数値)を返します。

Strings::ord('©'); // 0xA9

正規表現

Stringsクラスは正規表現を扱うための関数を提供します。ネイティブのPHP関数とは異なり、よりわかりやすいAPI、より良いUnicodeサポート、そして特にエラー検出を備えています。式のコンパイルまたは処理中のエラーはすべて Nette\RegexpException 例外をスローします。

split (string $subject, string $pattern, bool $captureOffset=false, bool $skipEmpty=false, int $limit=-1, bool $utf8=false)array

正規表現に従って文字列を配列に分割します。括弧内の式もキャプチャされ、返されます。

Strings::split('hello, world', '~,\s*~');
// ['hello', 'world']

Strings::split('hello, world', '~(,)\s*~');
// ['hello', ',', 'world']``

$skipEmptytrue の場合、空でない項目のみが返されます:

Strings::split('hello, world, ', '~,\s*~');
// ['hello', 'world', '']

Strings::split('hello, world, ', '~,\s*~', skipEmpty: true);
// ['hello', 'world']

$limit が指定されている場合、制限までの部分文字列のみが返され、文字列の残りは最後の要素に配置されます。制限-1または0は制限なしを意味します。

Strings::split('hello, world, third', '~,\s*~', limit: 2);
// ['hello', 'world, third']

$utf8true の場合、評価はUnicodeモードに切り替わります。u 修飾子を指定した場合と同様です。

$captureOffsettrue の場合、発生する各一致について、文字列内の位置(バイト単位、$utf8 が設定されている場合は文字単位)も返されます。これにより、戻り値が配列に変更され、各要素は一致した文字列とその位置のペアになります。

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

文字列内で正規表現に一致する部分を検索し、見つかった式と個々の部分式を含む配列、または null を返します。

Strings::match('hello!', '~\w+(!+)~');
// ['hello!', '!']

Strings::match('hello!', '~X~');
// null

$unmatchedAsNulltrue の場合、キャプチャされなかった部分パターンはnullとして返されます。それ以外の場合は、空の文字列として返されるか、返されません:

Strings::match('hello', '~\w+(!+)?~');
// ['hello']

Strings::match('hello', '~\w+(!+)?~', unmatchedAsNull: true);
// ['hello', null]

$utf8true の場合、評価はUnicodeモードに切り替わります。u 修飾子を指定した場合と同様です:

Strings::match('žlutý kůň', '~\w+~');
// ['lut']

Strings::match('žlutý kůň', '~\w+~', utf8: true);
// ['žlutý']

パラメータ $offset を使用して、検索を開始する位置(バイト単位、$utf8 が設定されている場合は文字単位)を指定できます。

$captureOffsettrue の場合、発生する各一致について、文字列内の位置(バイト単位、$utf8 が設定されている場合は文字単位)も返されます。これにより、戻り値が配列に変更され、各要素は一致した文字列とそのオフセットのペアになります:

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

文字列内で正規表現に一致するすべての出現箇所を検索し、見つかった式と個々の部分式を含む配列の配列を返します。

Strings::matchAll('hello, world!!', '~\w+(!+)?~');
/* [
	0 => ['hello'],
	1 => ['world!!', '!!'],
] */

$patternOrdertrue の場合、結果の構造が変更され、最初の項目が完全なパターン一致の配列、2番目の項目が最初の括弧内の部分パターンに一致する文字列の配列、というようになります:

Strings::matchAll('hello, world!!', '~\w+(!+)?~', patternOrder: true);
/* [
	0 => ['hello', 'world!!'],
	1 => ['', '!!'],
] */

$unmatchedAsNulltrue の場合、キャプチャされなかった部分パターンはnullとして返されます。それ以外の場合は、空の文字列として返されるか、返されません:

Strings::matchAll('hello, world!!', '~\w+(!+)?~', unmatchedAsNull: true);
/* [
	0 => ['hello', null],
	1 => ['world!!', '!!'],
] */

$utf8true の場合、評価はUnicodeモードに切り替わります。u 修飾子を指定した場合と同様です:

Strings::matchAll('žlutý kůň', '~\w+~');
/* [
	0 => ['lut'],
	1 => ['k'],
] */

Strings::matchAll('žlutý kůň', '~\w+~', utf8: true);
/* [
	0 => ['žlutý'],
	1 => ['kůň'],
] */

パラメータ $offset を使用して、検索を開始する位置(バイト単位、$utf8 が設定されている場合は文字単位)を指定できます。

$captureOffsettrue の場合、発生する各一致について、文字列内の位置(バイト単位、$utf8 が設定されている場合は文字単位)も返されます。これにより、戻り値が配列に変更され、各要素は一致した文字列とその位置のペアになります:

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]],
] */

$lazytrue の場合、関数は配列の代わりに Generator を返します。これは、大きな文字列を扱う際に重要なパフォーマンス上の利点をもたらします。ジェネレータを使用すると、文字列全体を一度にではなく、一致を段階的に検索できます。これにより、非常に大きな入力テキストでも効率的に作業できます。さらに、探している一致が見つかった時点でいつでも処理を中断できるため、計算時間を節約できます。

$matches = Strings::matchAll($largeText, '~\w+~', lazy: true);
foreach ($matches as $match) {
    echo "見つかりました: $match[0]\n";
    // 処理はいつでも中断できます
}

replace (string $subject, string|array $pattern, string|callable $replacement='', int $limit=-1, bool $captureOffset=false, bool $unmatchedAsNull=false, bool $utf8=false)string

正規表現に一致するすべての出現箇所を置換します。$replacement は置換文字列のマスクまたはコールバックです。

Strings::replace('hello, world!', '~\w+~', '--');
// '--, --!'

Strings::replace('hello, world!', '~\w+~', fn($m) => strrev($m[0]));
// 'olleh, dlrow!'

この関数は、2番目のパラメータに pattern => replacement の形式で配列を渡すことで、複数の置換を実行することもできます:

Strings::replace('hello, world!', [
	'~\w+~' => '--',
	'~,\s+~' => ' ',
]);
// '-- --!'

パラメータ $limit は実行される置換の数を制限します。制限-1は制限なしを意味します。

$utf8true の場合、評価はUnicodeモードに切り替わります。u 修飾子を指定した場合と同様です。

Strings::replace('žlutý kůň', '~\w+~', '--');
// 'ž--ý --ůň'

Strings::replace('žlutý kůň', '~\w+~', '--', utf8: true);
// '-- --'

$captureOffsettrue の場合、発生する各一致について、文字列内の位置(バイト単位、$utf8 が設定されている場合は文字単位)もコールバックに渡されます。これにより、渡される配列の形式が変更され、各要素は一致した文字列とその位置のペアになります。

Strings::replace(
	'žlutý kůň',
	'~\w+~',
	function (array $m) { dump($m); return ''; },
	captureOffset: true,
);
// dumps [['lut', 2]] と [['k', 8]]

Strings::replace(
	'žlutý kůň',
	'~\w+~',
	function (array $m) { dump($m); return ''; },
	captureOffset: true,
	utf8: true,
);
// dumps [['žlutý', 0]] と [['kůň', 6]]

$unmatchedAsNulltrue の場合、キャプチャされなかった部分パターンはnullとしてコールバックに渡されます。それ以外の場合は、空の文字列として渡されるか、渡されません:

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']
バージョン: 4.0