PHP4.3.0以降搭載されているglob関数は、パス文字列を引数に与えることでパターンマッチするパスを探して配列として返してくれる便利な関数です。パターンマッチということで、正規表現のパターンを与えるとマッチングをしてくれるPCRE関数(preg_matchなど)に近いように思われますが、globが解釈するパターンはUNIXシェルのパス名マッチのパターンであり、正規表現より煩雑にならない書き方ができるようです。
たとえば前回preg_grep関数と正規表現を用いて実装した、ディレクトリを検索してその中の拡張子が.jpgのファイルだけ抽出し、セレクトメニューの項目名にするという処理は、globを使うとこのような感じになります。
<?php $dir = "sample"; $parentlength = strlen($dir) + 1; echo '<form name="" method="" action=""><select name="">'; foreach(glob($dir."/*.csv") as $val){ echo '<option value="'.htmlentities(substr($val,$parentlength),ENT_QUOTES,"UTF-8").'">' .htmlentities(substr($val,$parentlength),ENT_QUOTES,"UTF-8").'</option>'; } echo '</select><input type="submit" value="表示"></form>'; ?> |
preg_grepでの例の再現のため、項目名としてファイル名のみを取り出そうとしてややこしくなっている部分はありますが、注目すべきはかの例にあったscandir関数のような、ディレクトリ内のパスを取得し配列に納めるというプロセスが省略されているという点です。glob関数はパス検索に特化しており、scandirの直接の上位互換と捉えても良いかもしれません。
さて、関数の説明です。まずパターン文字列の表記方法ですが、PCRE関数のように文字列の前後をスラッシュで囲む必要は無く、パスにワイルドカードなどの特殊記号を交えたものをそのまま与えます。以下が特殊記号です。
記号 | 意味 | 使用例 | マッチするテキスト |
*(アスタリスク) | 0文字以上の任意の文字列(ワイルドカード) | /home/*/lib | /home/userA/lib,home/userB/lib |
?(クエスチョンマーク) | 任意の1文字 | /img/img???.jpg | /img/img001.jpg,/img/img002.jpg |
¥(円マーク) | 特殊文字のエスケープ(windows) | /post.php¥?* | /post.php?post=”” |
\(バックスラッシュ) | 特殊文字のエスケープ(windows以外) | /post.php\?* | /post.php?post=”” |
[](角括弧) | 括弧内に現れる文字のどれか | /te[xs]t.php | /text.php,/test.php |
-(ハイフン)を使った応用編 | /te[a-z]t.php | /tebt.php,/tewt.php(aからzまで可) | |
-(ハイフン)を使った応用編 | /te[1-9]t.php | /te3t.php,/te8t.php(1から9まで可) | |
!(エクスクラメーション)は角括弧中で否定の意 | /te[!nx]t.php | /test.php(text,tentはダメ) |
正規表現と細かな違いがありますね。アスタリスクがワイルドカードの役割をするという辺りは、CSSやSQLの熟練者にはわかり易くて良いのではないでしょうか。
書式と定数の説明です。
glob(引数1,引数2); 引数1 : パターン文字列 引数2 : オプションフラグ。省略可。以下の定数をとり得る。 GLOB_MARK ディレクトリがマッチした場合最後にセパレータのスラッシュを付加 GLOB_NOSORT 結果として返す配列をソートしない(デフォルトはソート) GLOB_NOCHECK マッチする結果が無かった場合、検索パターン自体を返す GLOB_NOESCAPE エスケープ文字(¥,\)を機能させない GLOB_BRACE {パターン1,パターン2,パターン3}という指定で複数パターンの検索をする GLOB_ONLYDIR マッチしたディレクトリのみを返す GLOB_ERR エラー時に停止する(PHP5.1.0以降) |
正規表現における|(パイプライン)でのOR検索は、引数にGLOB_BRACEを与えた上で{}(中括弧)で括って行う必要があります。
preg_grepを使った例では、読み込んだファイル名を一旦ユーザインターフェースに出力しユーザに選ばせるという、完全にリモートのWEBサービスを意識した構成でした。それに対してglobの強みが生きてくるのは、ディレクトリに追加されたファイルを強制的に全部読み込んで表示するといった、ユーザの了解を省略したローカルディレクトリベースのアプリケーションなのかもしれません。
ピンバック: PHPでシンプルな文字列検索をする | AkisiのWEB制作日記