リダイレクトの基礎復習
今までなんとなくつかっていたので、あらためて、基礎復讐。
リダイレクション
リダイレクションは入出力先などを任意に変える仕組み。
lsコマンドの例
lsコマンドを普通に実行すると
1:シェルが標準入力(キーボード)からlsコマンドを実行しなさいという命令をうける
2:シェルがlsコマンドを実行し、その結果を受け取る
3:シェルは貰った結果を、標準出力(端末画面)に書きだす
ここで出力先をfileというファイルに変えてみましょう。
ls > file
このようにすると、標準出力先が端末画面からfileというファイルに変更され、lsコマンドの実行結果が、fileに書きこまれます。
ファイルディスクリプタ番号の省略
今まで「ls > ls_list」や「cat < file」などと、「>」「<」を何気なく使ってましたが、これらはファイルディスクリプタ番号を省略した形であり、
command > file
は
command 1> file
と同義です。
また
command < file
は
command 0< file
と同義です。
0と1は良く使う&固定値なので、省略可能になっているわけです。
練習問題
今「file1」「file2」というファイルが存在するとします。
「file1」は読み込み可ですが、「file2」は読み込み不可です。
下記にコマンド例を書くので、それぞれ標準出力と標準エラー出力がどこに出力されるのか答えてみましょう
第一問
cat file* > result
第二問
cat file* 2> result
第三問
cat file* > result 2> result2
第四問
cat file* > result 2> /dev/null
第五問
cat file* > result 2> result
第六問
cat file* > result 2>> result
第七問
cat file* > result 2>&1
第八問
cat file* 2>&1 > result
練習問題の答え
第三問
cat file* > result 2> result2
- 標準出力
- resultに出力
- file1の内容がでる
- 標準エラー出力
- result2に出力
- file2はpermission errで開けない旨
第四問
cat file* > result 2> /dev/null
- 標準出力
- resultに出力
- file1の内容がでる
- 標準エラー出力
- どこにもでない
- /dev/nullにリダイレクションすると結果を捨てる
第五問
cat file* > result 2> result
- 標準出力
- resultに出力
- file1の内容がでるが、すぐに消されるため確認できない
- 標準エラー出力
- resultに出力
- file2を開けないエラーメッセージで、resultファイルを上書きする
第六問
cat file* > result 2>> result
- 標準出力
- resultに出力
- file1の内容
- 標準エラー出力
- resultに追加出力
- fiile1の内容に続いて、file2を開けないエラーメッセージを、resultファイルを追加書き込みする
第七問
cat file* > result 2>&1
- 標準出力
- resultに出力
- file1の内容
- 標準エラー出力
- resultに出力
- fiile1の内容に続いて、file2を開けないエラーメッセージを、resultファイルを書き込みする
練習問題の補足
第六問と第七問の違い
第六問と第七問は結果が同じようにみえて、実は違います。
第六問は標準出力が終わってから、標準エラーを出力して追加書き込みしています。
たとえば、file1〜file100まであり、奇数の数字のファイルは読み込み不可だとしましょう。
すると、第六問のやり方では、file2〜〜file100までの偶数ファイルの内容がresultに書かれたのち、その次の行からfile1〜〜99の奇数ファイルが読み込めないエラーが書き込まれます。
一方、第七問のやり方では、標準出力の結果と標準エラー出力の結果が時系列できちんと一行ずつ書き込まれます。
多くの場合、第七問のやり方を利用する場合が多いでしょう。
OSの文字コードとlogの文字コードが異なり、tailなどで文字化ける場合の対処
あまりないかもしれないけど、実際に出くわしちゃったので、対処法をメモ
nkf
nkf っての使います
nkf Network Kanji Filter プロジェクト日本語トップページ - SourceForge.JP
Linuxコマンド集 - 【 nkf 】 文字コードを変換する:ITpro
なければ入れて
sudo apt-get install nkf
文字コード指定
オプションがいろいろある
-u 出力時にバッファリングを行わない -j JISコードに変換する -e EUCコードに変換する -s シフトJISコードに変換する -w UTF8コードに変換する
まぁ自分の環境に合わせてください
自分の.bashrcではaliasを
alias log='sudo tail -f /var/log/apache/error.log | nkf -u -w'
こんな感じにしてます。
debian lenny の screen にはutf8周りにバグがあるらしいので、入れ直したログ
具体的には、日本語を含む文字をコピペやら改行やらすると、表示がくずれる。
えらい盛大に。。。
UTF-8環境で GNU Screen の日本語表示が崩れる件 - OSのようなもの
修正パッチがあるようなので、apt-getやめて入れ直す事に
sudo apt-get remove screen ※設定ファイルも残したくなければ、 sudo apt-get --purge remove screen
本体落としてきて
mkdir ~/tmp cd tmp wget ftp://ftp.uni-erlangen.de/pub/utilities/screen/screen-4.0.3.tar.gz tar zxf screen-4.0.3.tar.gz cd screen-4.0.3
パッチを持ってくる
screen install memo (UNIX)
たぶん、一番下のcjkwidth(chinese japanese korean width)ってのだけで大丈夫だと思うけど、とりあえず全部当ててみる
wget ftp://www.dekaino.net/pub/screen/screen-4.0.2-deadlock-patch wget ftp://www.dekaino.net/pub/screen/screen-4.0.2-hankanacopy-patch wget ftp://www.dekaino.net/pub/screen/screen-4.0.2-patch-cjkwidth-cvs-2006052001
パッチあてて
patch < screen-4.0.2-deadlock-patch patch < screen-4.0.2-hankanacopy-patch patch < screen-4.0.2-patch-cjkwidth-cvs-2006052001
コンパイルに必要なもんを、apt-get で入れておきましょう
sudo apt-get build-dep screen
このまま configure すると、エラーになる
configure: error: !!! no tgetent - no screen
これは
sudo apt-get install libncurses5-dev
で解決
./configure --enable-colors256 --prefix=/usr/local/ make su make install
解決
よかったよかった
オブジェクトのメソッド一覧(メモ
クラスメンバはインスタンス生成して dump すれば見れるけど、クラスメソッド見る方法ぐぐったので、メモ。
$methods = get_class_methods("ClassName");
でいけるらしい。
$obj = new OBJ; var_dump(get_class_methods(get_class($obj)));
メモ。
is_dirを含むスクリプトを他階層から実行する場合の注意 (自分用メモ
あるディレクトリのファイル一覧取得して、File か Directory かを調べる簡単なscript
check_dir.php は "/home/ryoff/prac_php/" にあるとする。
-- prac_php |-- check_dir.php |-- fuga.php `-- hoge `-- foo.php
vi check_dir.php
<?php $dir = "/home/ryoff/prac_php/"; if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { if (is_dir($file)) { echo "DIR : " . $file . "\n"; } else { echo "FILE: " . $file . "\n"; } } closedir($dh); } } ?>
これを、check_dir.php が置いてある階層以外からたたくと、
FILE: fuga.php FILE: check_dir.php DIR : .. FILE: hoge DIR : .
こんな感じで、hoge は Directory のはずなのに、File と認識されてしまった。
Perlでもこんなことあったな。
と思った。
自作モジュールをuseするときの注意点 - 雑想空間
Perlだと[FindBin]があるからいいんだけど、phpだとどうすればいいんだろう?
if (is_dir($dir.$file)) {
とりあえず、絶対パスにして応急処置ww
あとで調べる
php splitは非推奨になったようですね。(自分用メモ
$str = "a-b-c-d";
こんなのを/-/でsplitしたくなって、split関数つかったらwarningsでた。
PHP Deprecated: Function split() is deprecated in
「分かったよ。何かエラーでたらphp pro行けばいいんだろ」
ってことで、見てみると
警告
この関数は PHP 5.3.0 で 非推奨となりました。 この機能を使用しないことを強く推奨します。
と赤字で大きく書いてある。
注意: PHP 5.3.0 以降、 regex 拡張モジュールは非推奨となりました。かわりに PCRE 拡張モジュール を使うことが推奨されています。 この関数をコールすると E_DEPRECATED が発生します。 PCRE への変換についてのヘルプは 相違点の一覧 を参照ください。
なるほどね
splitの代わりに
ご丁寧にちゃんと代替方法が紹介されている。
Perl 互換の正規表現構文を使用する preg_split() は、往々にして split() よりも速い代替案となります。 正規表現の威力が必要ないのであれば、explode() を使用するほうがより高速です。これは正規表現エンジンの オーバーヘッドを受けません。
Perl の @chars = split('', $str) と同等の処理をする方法を知りたい場合は、 preg_split() あるいは str_split() の例を参照ください。
Perl互換の正規表現使いたいなら preg_split() で、特に必要なければ explode() ってことか。
str_split() は確かに文字を一文字ずつバラバラにするにはいいけど、それ以外には使いにくそう。
$st = "a-b-c-d"; print_r(preg_split('/-/', $st)); print_r(explode('-', $st));
何かしたいときに、その実現方法が組み込み関数にあるのかないのか調べるオーバーヘッドが高い・・。
Smartyクラスを継承して使いやすいように拡張。(php proの拡張セットアップがなぜかうまく動かなかったので・・。
拡張セットアップ - PHPプロ!マニュアル
こちらを参考に色々やってみた。
参考ソース
<?php require('Smarty.class.php'); class Smarty_Test extends Smarty { function Smrty_Test() { $this->Smarty(); $this->template_dir = '(ファイルの絶対パス)/smarty_test/templates/'; $this->compile_dir = '(ファイルの絶対パス)/smarty_test/templates_c/'; $this->config_dir = '(ファイルの絶対パス)/smarty_test/configs/'; $this->cache_dir = '(ファイルの絶対パス)/smarty_test/cache/'; $this->caching = true; $this->assign('app_name', 'Smarty Test'); } } ?>
呼び出し元は
vi smarty_test/htdocs/index.php
<?php require_once('../setup.php'); $smarty = new Smarty_Test(); $smarty->assign('name','Ryoff'); $smarty->display('index.tpl'); ?>
ほぼ(ってか全て)、php proからソース持ってきただけです
これ動かすと、
Warning: Smarty error: unable to read resource: "index.tpl" in /usr/local/lib/php/Smarty/Smarty.class.php on line 1093 Fatal error: Smarty error: the $compile_dir 'templates_c' does not exist, or is not a directory. in /usr/local/lib/php/Smarty/Smarty.class.php on line 1093
こんなエラーでてうまくいかねぇ。
var_dumpしてみると、コンストラクタうまく呼び出せてない感じ。
なんでだろう、って調べたら、どうやらこれは php4 の記述方法らしい。
php5では
Andante PHP、Smartyクラスを継承して拡張したい
↑のサイト様にお世話になりました。
parent::__construct(); //親クラス初期化
こんな感じで親のコンストラクタを明示的に呼び出せるらしい。
なので書き直してみた。
vi smarty_test/setup.php
<?php require('Smarty.class.php'); class Smarty_Test extends Smarty { public function __construct() { parent::__construct(); //親クラス初期化 $this->template_dir = '(ファイルの絶対パス)/smarty_test/templates/'; $this->compile_dir = '(ファイルの絶対パス)/smarty_test/templates_c/'; $this->config_dir = '(ファイルの絶対パス)/smarty_test/configs/'; $this->cache_dir = '(ファイルの絶対パス)/smarty_test/cache/'; $this->caching = true; $this->assign('app_name', 'Smarty Test'); } } ?>
動いた。
非常に勉強になりました。