文字列操作って色々あるけどどうなの?

2014年11月5日(水)
原田 裕介(はらだゆうすけ)
基本的な機能として、特に意識せずに使っている文字列操作。 似た機能の違いを理解して使い分けるのがポイントです。

シングルクォートとダブルクォート

文字列などを囲う際に使われる、シングルクォート「'」とダブルクォート「"」は何が違うのでしょう? どちらも動作的には同じように見えるので、深く考えずに使っている方も多いかと思います。(バッククォート「`」は、また別物です。バッククォートで囲んだ文字列はシェルとして実行されてしまうので、間違えないように注意してください。)

まずは普通に使ってみましょう。

3_7_singlequote.php

<?php
echo 'Hello World!';

出力結果

>php 3_7_singlequote.php
Hello World!

3_7_doublequote.php

<?php
echo "Hello World!";

result

>php 3_7_doublequote.php
Hello World!

普通に文字列を表示させるだけなら、同じですね。では、どこが異なるのかと言うと、ダブルクォートでは変数やエスケープの展開ができる点です。

3_8_singlequote.php

<?php
$test = 'world';
echo 'Hello $test!\nhello hello';

出力結果

>php 3_8_singlequote.php
Hello $test!\nhello hello

3_8_doublequote.php

<?php
$test = 'world';
echo "Hello $test!\nhello hello";

出力結果

>php 3_8_doublequote.php
Hello world!
hello hello

このように、ダブルクォートは変数やエスケープを展開できますが、シングルクォートはそのまま出力されてしまいます。

クォートの種類によるパフォーマンスの差

「ダブルクォートは変数展開やエスケープ処理などを行っているため、シングルクォートよりも遅く、通常の文字列を扱う場合はシングルクォートに統一すべき」という意見を、見聞きすることがあります。これは本当でしょうか。この辺りは少し疑問に思ったので、調べてみることにしましょう。「憶測するな、計測せよ」です。

3_9_doublequote.php

<?php
$startTime = microtime(true);

$test = 'world';
for($i = 0; $i < 100000; $i++){
  echo "Hello $test!\nhello hello ${test}\n";
}

echo PHP_EOL, PHP_EOL;

echo microtime(true) - $startTime, '秒';

出力結果

>php 3_9_doublequote.php
Hello world!
hello hello world
Hello world!
hello hello world
:
省略
:
10.614315986633秒

3_9_singlequote.php

<?php
$startTime = microtime(true);

$test = 'world';
for($i = 0; $i < 100000; $i++){
  echo 'Hello $test!\nhello hello ${test}';
  echo PHP_EOL;
}

echo PHP_EOL, PHP_EOL;

echo microtime(true) - $startTime, '秒';

出力結果

>php 3_9_singlequote.php
Hello $test!\nhello hello ${test}
Hello $test!\nhello hello ${test}
:
省略
:
10.541589021683秒

ダブルクォート シングルクォート
10.779225111008秒
11.07807302475秒
10.614315986633秒
11.040370941162秒
10.77766084671秒
10.541589021683秒

何も変わりませんね。

確かにダブルクォートは変数やエスケープの展開処理がありますが、このように実際に動かして比較してみるとたいして違いが出ません。というよりほとんど一緒です。

「ぶっちゃけどっちもそんなに変わらない」ということがわかったので、どちらでも使いやすいほうを選びましょう。ただしチームで開発する場合は、宗教戦争になりがちなので、あらかじめコーディング規約で定めておくのが良いのではないでしょうか?

printfとsprintf

似たような文字列成形系の関数として、printfとsprintfがありますが、両者はどこが違うのでしょう?PHPマニュアルを見てみましょう。

printf フォーマット済みの文字列を出力する
sprintf フォーマットされた文字列を返す

それぞれ、フォーマットに従って文字列を成形してくれる点は一緒ですが、printfが結果を画面に出力してくれるのに対し、sprintfは値を返します。sprintfは成形した文字列を変数に入れたり、関数に引数として与えたい場合などに利用できます。

sprintf は出力を行いませんので、成形後に出力する場合は

echo sprintf(...);

とする必要があります。以下の例のように、いったん文字列に一回格納してから使いたい場合に便利ですね。

$text = sprintf(...);

PHPは自動で型変換してくれるので、次に示す3_10_yen.phpのような書き方はあまりしませんが、数字を文字列に入れる時はこのようにします。

3_10_yen.php

<?php
printf("今お財布には%d円あります", $yen);

出力結果

>php 3_10_yen.php
今お財布には0円あります

またprintfは、下記のように桁数が足りない場合に先頭を0で埋めて桁をそろえたり、年月日を揃えたりするのによく使われます。

3_10_zero.php

<?php
printf("%04d", 13);

出力結果

>php 3_10_zero.php
0013

3_10_time.php

<?php
printf("%04d-%02d-%02d", 2010, 8, 15);

出力結果

>php 3_10_time.php
2010-08-15

今までなんとなく使って来た方も多いと思われる文字列操作ですが、細かいところを見ていくと実はこのように色々とクセがあります。PHPは自由な言語と言われていますが、その自由さを許容するために、このようなクセがあるのです。こういった細部にも気を配ってコードを書いていくと、より良いコードになるのではないでしょうか?

次回はオブジェクトと参照渡しについてお話ししていきます。

著者
原田 裕介(はらだゆうすけ)
株式会社ユーザーローカル
東京都在住。携帯のホームページ作成サービスでHTMLのコーディングを始めて、PHPerとなる。
株式会社ハッシュシステム代表取締役やtetolの立ち上げ、株式会社イードでニュースメディアの開発やエンジニア採用を経て、現在はアクセス解析ツールの開発を行いながら、個人でもWEBサービスの開発を行っている。PHP技術者認定上級試験の認定者でもあり、受賞歴はmixi scrap challenge優勝など。

 

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています