shellgei/shellgei160

問題9「ログの抽出」につきまして

hirofumimurai opened this issue · 2 comments

本書で紹介されている「teip」コマンドで、日付を整理してから解きたいと考えていました。
以下のようなワンライナーを試みたのですが、期待通りの結果が得られませんでした。

$cat log_range.log | teip -f 4-5 -- bash -c 'sed "s;[;;" | sed "s;];;" | sed "s;/;;g" | date -f - +"%Y%m%d%H%M%S"'

技術的なアドバスをいただきたいです。

よろしくお願いいたします。

一旦 log_range.log の日付を整理したい状況と理解しました。
また [29/Dec/2016 23:22:10] のように日付の個所の角括弧を除いて、その中身を date に与えたい状況にお見受けします。

こちらについて、2 点気づきましたので、問題の切り分けにご活用ください。

teip の挙動

teip には -f オプションではなく、-og オプションで、正規表現でマッチした範囲だけを選択できるので、こちらの表現にして動作をお試しいただくと良いかも知れません。
teip の挙動として teip -f 4-5 という指定をすると、4列目と5列目がそれぞれ独立してbashコマンドに与えられてしまうため、まとめて日付として扱うことができません。
下記のコマンドで、どのような範囲が選択できるかご確認いただけると思います。teip -f 4-5 と比較をいただけると。

$ cat log_range.log | teip -og '\[.*\]'
︙

なお、[] は正規表現で使われるので \ でエスケープしています。

bash 内の sed について

私の手元で確認する限り sed "s;[;;" | sed "s;];;" の個所も、[] は正規表現として扱われているので、上記と同様にエスケープが必要に見えます。

上記の点を確認の上、改めてチャレンジいただけると良いと思いました。
もし追加で不明点があればご連絡ください。

アドバイスありがとうございます。理解することができました。
teipコマンドで、ひとつの列(フィールド)として、抽出する必要があるということを理解いたしました。

以下のワンライナーで、解答を得ることができました。

$cat log_range.log | awk '{print "STX"$4,$5"EOT",$0}'| teip -og STX.*EOT -- bash -c 'sed "s;STX\[;;" | sed "s;\/;;g" | sed "s;\]EOT;;" | date -f - +"%Y%m%d%H%M%S"' | awk '$1>=20161224210000 && $1<20161225040000' | awk '{$1="";print $0}'

また、ご指摘のとおり、sedの部分の[と]は、エスケープ必要でした。

書籍の解答や別解より、かなり長くなってしまいますが、数値の大小比較のみへと問題を落とし込めるので、自分の感覚的には理解しやすいです。

teipコマンドは、シェルでデータを扱う際、使用価値が高いので、これからも使わせていただこうと思っています。

今回は、アドバイスいただき、ありがとうございました。