文字列の操作
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']``
$skipEmpty
が true
の場合、空でない項目のみが返されます:
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']
$utf8
が true
の場合、評価はUnicodeモードに切り替わります。u
修飾子を指定した場合と同様です。
$captureOffset
が true
の場合、発生する各一致について、文字列内の位置(バイト単位、$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
$unmatchedAsNull
が true
の場合、キャプチャされなかった部分パターンはnullとして返されます。それ以外の場合は、空の文字列として返されるか、返されません:
Strings::match('hello', '~\w+(!+)?~');
// ['hello']
Strings::match('hello', '~\w+(!+)?~', unmatchedAsNull: true);
// ['hello', null]
$utf8
が true
の場合、評価はUnicodeモードに切り替わります。u
修飾子を指定した場合と同様です:
Strings::match('žlutý kůň', '~\w+~');
// ['lut']
Strings::match('žlutý kůň', '~\w+~', utf8: true);
// ['žlutý']
パラメータ $offset
を使用して、検索を開始する位置(バイト単位、$utf8
が設定されている場合は文字単位)を指定できます。
$captureOffset
が true
の場合、発生する各一致について、文字列内の位置(バイト単位、$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!!', '!!'],
] */
$patternOrder
が true
の場合、結果の構造が変更され、最初の項目が完全なパターン一致の配列、2番目の項目が最初の括弧内の部分パターンに一致する文字列の配列、というようになります:
Strings::matchAll('hello, world!!', '~\w+(!+)?~', patternOrder: true);
/* [
0 => ['hello', 'world!!'],
1 => ['', '!!'],
] */
$unmatchedAsNull
が true
の場合、キャプチャされなかった部分パターンはnullとして返されます。それ以外の場合は、空の文字列として返されるか、返されません:
Strings::matchAll('hello, world!!', '~\w+(!+)?~', unmatchedAsNull: true);
/* [
0 => ['hello', null],
1 => ['world!!', '!!'],
] */
$utf8
が true
の場合、評価はUnicodeモードに切り替わります。u
修飾子を指定した場合と同様です:
Strings::matchAll('žlutý kůň', '~\w+~');
/* [
0 => ['lut'],
1 => ['k'],
] */
Strings::matchAll('žlutý kůň', '~\w+~', utf8: true);
/* [
0 => ['žlutý'],
1 => ['kůň'],
] */
パラメータ $offset
を使用して、検索を開始する位置(バイト単位、$utf8
が設定されている場合は文字単位)を指定できます。
$captureOffset
が true
の場合、発生する各一致について、文字列内の位置(バイト単位、$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]],
] */
$lazy
が true
の場合、関数は配列の代わりに 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は制限なしを意味します。
$utf8
が true
の場合、評価はUnicodeモードに切り替わります。u
修飾子を指定した場合と同様です。
Strings::replace('žlutý kůň', '~\w+~', '--');
// 'ž--ý --ůň'
Strings::replace('žlutý kůň', '~\w+~', '--', utf8: true);
// '-- --'
$captureOffset
が true
の場合、発生する各一致について、文字列内の位置(バイト単位、$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]]
$unmatchedAsNull
が true
の場合、キャプチャされなかった部分パターンは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']