PHP - 文字列操作

公開日:2020-12-22 更新日:2020-12-22
[PHP]

1. 概要

文字列操作についてです。

2. 文字列長の取得

文字列の長さを取得します。
$len = strlen('Hello');
var_dump($len);
実行結果
int(5)

3. マルチバイト文字列について

日本語の文字列長を取得すると、文字数より大きい値が返ってきます。
var_dump( strlen('あいうえお') );
実行結果
int(15)

文字には文字コードが振られていますが、日本語の場合は、1文字を表現するのに複数バイト使用します。
これをマルチバイト文字と呼びます。
そのため、日本語を含む文字列長を strlen() で取得すると、予想外の結果となります。

日本語を含む文字列長を取得するに マルチバイト文字列に対応した mb_strlen() を使います。
mb_strlen() 以外にも、先頭に「mb_」が付くマルチバイト文字列に対応した関数が用意されています。
var_dump( mb_strlen('あいうえお') );

実行すると、おそらく次のエラーが発生します。
Fatal error: Uncaught Error: Call to undefined function mb_strlen()

エラーが出た場合は、
PHP をインストールしたフォルダにある php.ini-development をコピーして、php.ini を作成します。
既に php.ini がある場合は、コピーしなくて大丈夫です。
php.ini ファイルを開いて、次の行を探します。
;extension=mbstring
見つかったら、次のように、先頭の「;」を削除して、php_mbstring.dll のフルパスを指定します。
extension=C:/php74/ext/php_mbstring.dll

もう一度実行して、エラーが出なければ OK です。
実行結果
int(5)

mbstring 以外にも、必要に応じて、上記のようにして関数を使えるようにする必要があります。

4. 文字列の一部分の取得

substr()、mb_substr() を使います。文字列の先頭や末尾の削除する際にも使えます。
引数1 対象文字列、
引数2 取得する開始位置(開始インデックス。0 から始まる。)
引数3 取得する文字数
var_dump( substr('abcdefg', 0, 5) );
var_dump( substr('abcdefg', 3, 5) );
var_dump( mb_substr('あいうえおかきくけこ', 0, 5) );
var_dump( mb_substr('あいうえおかきくけこ', 5, 5) );
実行結果
string(5) "abcde"
string(4) "defg"
string(15) "あいうえお"
string(15) "かきくけこ"

また、開始位置をマイナスにすると、右から開始位置を指定できます。
実行結果
var_dump( substr('abcdefg', -5, 3) );
string(3) "cde"

5. 文字列の検索

文字列にある文字列を検索して位置を取得するには、strpos()、mb_strpos() を使います。
引数1 対象文字列
引数2 検索する文字列

戻り値は、見つかった位置をインデックスで返します。
見つからなかった場合は、false を返します。
var_dump( strpos('abcdefg', 'def') );
var_dump( mb_strpos('あいうえおかきくけこ', 'かきく') );
実行結果
int(3)
int(5)

また、見つからなかった場合は false を返すため、
見つかったかどうかを判定する場合は、
結果が 0 以上かどうかで判定すると、間違った結果となります。
次の例では、$idx2 は false になりますが、>= で判定すると false が 0 として扱われて、true になります。
$idx1 = strpos('abcdefg', 'abc');
$idx2 = strpos('abcdefg', 'xyz');

if ($idx1 >= 0) print("abc が見つかりました。\n");
if ($idx2 >= 0) print("xyz が見つかりました。\n");
実行結果
abc が見つかりました。
xyz が見つかりました。
見つかったかどうかの判定は、=== か !== を使ってください。
if ($idx1 === false) print("abc が見つかりませんでした。\n");
if ($idx2 === false) print("xyz が見つかりませんでした。\n");

if ($idx1 !== false) print("abc が見つかりました。\n");
if ($idx2 !== false) print("xyz が見つかりました。\n");
実行結果
xyz が見つかりませんでした。
abc が見つかりました。

6. 大文字・小文字の変換

strtoupper() で小文字を大文字に、
strtolower() で大文字を小文字に変換します。
var_dump( strtoupper('abcdefg') );
var_dump( strtolower('ABCDEFG') );
実行結果
string(7) "ABCDEFG"
string(7) "abcdefg"

7. 0埋め(ゼロパディング)

先頭または末尾を任意の文字で埋めたい場合は、str_pad() を使用します。
引数1 パディング対象の文字列
引数2 全体の文字数(桁数)。この文字数になるまでパディングします。
引数3 パディングする文字
引数4 先頭をパディングする場合は、STR_PAD_LEFT。末尾の場合は省略可能。
var_dump( str_pad('1234', 10, '0', STR_PAD_LEFT) );
var_dump( str_pad('12345678', 5, '0', STR_PAD_LEFT) );
var_dump( str_pad('abc', 5, '_') );
実行結果
string(10) "0000001234"
string(8) "12345678"
string(5) "abc__"

8. フォーマット

sprintf() を使うと、指定された値をフォーマットに従って変換します。
引数1 フォーマットを含んだ文字列
引数2~引数n 埋め込む値

フォーマット
%d は整数、%f は実数、%s は文字列
%と記号の間に桁数を指定できます。
この他にもたくさん書式があるので、公式サイトをご確認ください。
var_dump( sprintf('値=[%08d]'  , 123.456) ); // 整数。0埋め。
var_dump( sprintf('値=[%8d]'   , 123.456) ); // 整数。スペース埋め。
var_dump( sprintf('値=[%8.2f]' , 123.456) ); // 実数。少数第2位まで
var_dump( sprintf('値=[%08.3f]', 123.456) ); // 実数。少数第3位まで。0埋め。
var_dump( sprintf('値=[%8s]'   , 'abc') );   // 文字列
var_dump( sprintf('値=[%-8s]'   , 'abc') );  // 文字列。左寄せ

var_dump( sprintf("こんにちは。%sさん。", '一郎') );
var_dump( sprintf("%04d年%02d月%02d日", 2020, 1, 2) );
var_dump( sprintf("%04d-%02d-%02d:%s:%s", 2020, 3, 4, 'ERROR', 'エラーが発生しています。') );
実行結果
string(14) "値=[00000123]"
string(14) "値=[     123]"
string(14) "値=[  123.46]"
string(14) "値=[0123.456]"
string(14) "値=[     abc]"
string(14) "値=[abc     ]"
string(33) "こんにちは。一郎さん。"
string(17) "2020年01月02日"
string(53) "2020-03-04:ERROR:エラーが発生しています。"

9. 置換

str_replace() を使うと、文字列中の文字列を置換できます。
引数1 検索文字列。配列にして複数指定することも可能。
引数2 置換文字列。引数1に対応する配列にすることも可能。
引数3 対象文字列

var_dump( str_replace('___',  'pen', 'This is a ___.') );
var_dump( str_replace('___',  'dog', 'This is a ___.') );
var_dump( str_replace(['a', 'is', 'pen', 'This'],  ['1つの', 'です', 'ペン', 'これは'], 'This is a pen.') );
var_dump( str_replace(['This', 'pen', 'is', 'a'],  ['これは', 'ペン', 'です', '1つの'], 'This is a pen.') );
var_dump( str_replace(['1', '2', '3'],  '_', 'abc123abc123') );
実行結果
string(14) "This is a pen."
string(14) "This is a dog."
string(31) "Thです です 1つの ペン."
string(32) "これは です 1つの ペン."
string(12) "abc___abc___"
3つ目の例では、「This」が「Thです」となっています。
これは、先に「is」が「です」に置換されているためです。
文字列を複数置換する場合は、長い文字列から置換してください。
また、置換順序によって、置換された文字列が、さらに置換される場合もあります。

10. ヒアドキュメント

「<<<」+ ラベル(任意の文字列)から、ラベル(任意の文字列)+「;」までの範囲を、文字列として使うことができます。
改行した場合、改行コードも含まれます。
$s = <<<EOD
おはよう
こんにちは
こんばんは
EOD;

print($s);
実行結果
おはよう
こんにちは
こんばんは

また、ヒアドキュメント内では変数が値に展開されるため、
「$」を使う場合は、前に「\」を付けてエスケープする必要があります。
$value = 100;
$s = <<<EOD
\$v = $value
'' と "" はそのまま使える
あいうえお\nかきくけこ
さしすせそ\\nたちつてと
EOD;

print($s);
実行結果
$v = 100
'' と "" はそのまま使える
あいうえお
かきくけこ
さしすせそ\nたちつてと

また、「<<<」の後ろのラベルの部分を「'」で囲うと、エスケープする必要がなくなります。
これを、Nowdoc と呼びます。
$value = 100;
$s = <<<'EOD'
\$v = $value
'' と "" はそのまま使える
あいうえお\nかきくけこ
さしすせそ\\nたちつてと
EOD;

print($s);
実行結果
\$v = $value
'' と "" はそのまま使える
あいうえお\nかきくけこ
さしすせそ\\nたちつてと

11. 文字列の分割と結合

explode() を使うと、文字列を、指定された区切り文字列で分割して、配列にします。
implode() を使うと、配列を、指定された区切り文字列で結合して、1つの文字列にします。

次の例では、文字列を explode() で分割して、
implode() で結合して、元に戻しています。
$s = 'apple,banana,orange';
$fruits = explode(',', $s);
var_dump($fruits);

$s2 = implode(',', $fruits);
var_dump($s2);
実行結果
array(3) {
  [0]=>
  string(5) "apple"
  [1]=>
  string(6) "banana"
  [2]=>
  string(6) "orange"
}
string(19) "apple,banana,orange"

12. 文字列と数値の相互変換

文字列から数値に変換するには、floatval()、intval() を使い、
数値から文字列に変換するには、strval() を使います。
但し、意図的に変換しなくても、使う演算子によって自動的に変換されます。

また、intval()は、小数点以下を四捨五入せずに切り捨てて整数にする際にも使用します。
$s = '123.456';
$v = $s + 0.001;
var_dump(sprintf("%f", $s)); // string(10) "123.456000"

$s = '123.456';
$v = floatval($s) + 0.001;
var_dump(sprintf("%f", $s)); // string(10) "123.456000"

$s = strval($v);
var_dump((string)$v); // string(7) "123.457"
var_dump($v . '');    // string(7) "123.457"
var_dump($s);         // string(7) "123.457"

var_dump( intval('123.456') ); // int(123)
実行結果
string(10) "123.456000"
string(10) "123.456000"
string(7) "123.457"
string(7) "123.457"
string(7) "123.457"
int(123)