- Contents -
この記事では、コマンドライン引数で
複数ファイル指定して、一行ずつ処理する為の実装を
コピペして利用できるようにサンプルとして、ここに載せておきます。
指定ファイルを一行ずつ処理する
コマンドライン引数で、
指定したファイルを一行ずつ処理するようなスクリプト
php readline.php a.txt
realine.php というのは、
指定されたファイルを、
単純に一行ずつechoするスクリプトとします。
複数の指定ファイルを一行ずつ処理する
更に、コマンドライン引数に、
単一ファイルだけでなく、
複数指定したい場合もありますよね。
例えば、
php readline.php a.txt b.txt
または、ワイルドカードを利用して
php readline.php *.txt
こんな感じに利用しても、
同様に一行ずつ処理できると便利です。
実装サンプル
コマンドライン引数で、複数ファイルを指定しても、
全ファイルを、一行ずつ処理するような、
実装サンプルを記載していきましょう。
readline.php
<?php
// 引数に指定されたファイルを一つずつ処理
for ($i = 1; $i < $argc; $i++) {
$fileName = $argv[$i];
// ファイルを開く
$fp = @fopen($fileName, "r");
if (!$fp) {
fputs(STDERR, "Failed to open file: $fileName\n");
continue;
}
// 一行ずつ処理
while (false !== ($line = fgets($fp))) {
echo $line;
}
// ファイルを閉じる
fclose($fp);
}
ポイントとなる、変数、メソッドを説明しておきます。
$argv
コマンドライン引数を、配列の形で保持している。
e.g. ["readline.php", "a.txt", "b.txt"]
※配列の1番目は、PHPスクリプト自体のPATHが入っているので注意!
(シェルスクリプトと同じですね)
$argc
$argv
配列の配列長(サイズ)になります。
for ($i = 1; $i < $argc; $i++) {
$v = $argv[$i];
...
}
$argv
の1番目は、PHPスクリプト自体のPATHが入っているので、
添字は1から始める事で、引数のみでループする。
fgets
ファイルハンドルから、文字列を読み込むメソッド。
fgets ($handle [, $length ])
第二引数にバッファサイズを指定する事ができます。
指定しない場合、fgetsは、行末(一行ずつ)までを読み取ります。
プロセス置換を使う例
シェルのプロセス置換を利用すると、
PHP側で、わざわざ複数ファイル対応しなくても済みます。
php readline.php <(cat *.txt)
ただ、プロセス置換を利用した場合、
PHPのバージョンが古いと注意しないといけません。
古いPHPバージョンは注意
古いバージョンのPHPで、プロセス置換されたファイルを読み込むと
エラーが発生して、読み込めない。
PHP Warning: fopen(/dev/fd/63): failed to open stream: No such file or directory
これは、PHPのバージョンによるもので、
新しいバージョンであれば発生しません。
一時ファイルを許容するなら
他にも、そんなPHP実装しなくても、
一時ファイルを作成してから、渡すようでもいいでしょう。
ただ、ちょっと面倒ですけどね。
cat *.txt > all.txt
php readline.php all.txt
まとめ
コマンドライン引数で、複数ファイル指定して、
1行ずつ処理する、PHP実装のサンプルを記載しました。
プロセス置換を利用すれば、
PHP側では、単一ファイルの読み込みだけでも事足りるでしょう。
ただ、古いPHPの場合、エラーがでるので注意です。
同じ事を実現したいときに、
他の方法として、
標準入力を受け付けるようにしても、良いかもしれませんね。