ファイヤープロジェクト
TV番組欄チェックスクリプト
2003-08-25T20:45+09:00   matsu
私はとあるキーワードがTV番組欄にないか,しょっちゅうチェックしている.この単調なルーチンワークを自動化すべく,スクリプトを作成した.
いきなり作成した現物を示す(ライセンス).
...私が何をしたかったかはもうバレバレだろうか.とにかく使用方法.
  1. 変数KEY_WORDにチェックしたいキーワードを設定する.これは直接grepコマンドに渡すので,grepコマンドが認識できるスタイルの正規表現で設定できる.
  2. スクリプトを実行する.
  3. キーワードが引っかかった番組表URLのチェックリストが表示されるので,確認したいものを選択する.
  4. 選択したURLがブラウザで表示されるので,確認する.
チェックしたいキーワードをコマンド引数で渡すように実装することもできるが,今の私にとっては必要ない.
このスクリプトはかなり単純で,wgetして落したファイルにgrepをかけるだけである.が,恥かしながら作成時間は基本部分で1H程かかった(さらにチェックリストを表示,ブラウザ起動するためのバージョンアップでもう1H程かかった).以下に往生した点を示す.
  1. 各局のサイトの調査.大した作業じゃないはずなのに,なぜかこれに時間の大半を費す.
  2. dateコマンド,「date」って打つ意外使い方を知らない.
  3. grepの正規表現.\を忘れてハマる.
  4. gdialogでは選択した項目がstderrに出力され,しかも一行にずらっと表示される.
スクリプトで日付を操作するには,dateコマンドをある程度使いこなせなければ無駄な労力を費すことになる.ここでは以下のようにdateコマンドを使用した.
date --date "$I days" '+%Y%m%d'
これは,$Iに格納された日数分後の日付を年年年年月月日日で表示するものである.N日前を表示するには,
date --date "$N days ago"
とする.また,フォーマット文字列
'+%Y%m%d'
は+で始まる必要がある.
$?
$?は直前に実行した式の結果を格納する.grepしたとき,その出力はマッチした行が出力される.が,出力ではなく,返り値を取得したいときに,$?を使用する.例えば,関数check_generic内,
    grep -r $KEY_WORD $TEMP_FILE
    if [ $? -eq 0 ]
    then
	add_browse_list $2 $1;
    fi
の部分は,grepしてマッチした行を出力している.そして,if文で$?をチェックし,grepの返り値をチェックする.その値が0すなわちマッチした行があった場合,ダウンロードしたファイルのURLをadd_browse_listに渡し,後で表示するチェックリストの項目として登録している.
チェックリストはgdialogで実現している.gdialogの詳細はmanに譲るとして,ここではこのスクリプトでポイントとなる点だけを示す.
BROWSE_RESULT=$(gdialog --backtitle ${0##*/}\
--title ${0##*/} --checklist "select URL to browse."\
400 500 $BROWSE_LIST_NUM $BROWSE_LIST 2>&1);
チェックリストの項目は,先述のとおり,grepでマッチした場合にadd_browse_listを呼び出して$BROWSE_LISTに登録している.
function add_browse_list(){
    BROWSE_LIST="${BROWSE_LIST} $2 $1 off";
    let BROWSE_LIST_NUM+=1;
}
このように,ゴリゴリとgdialogに渡すパラメータを生成していく.gdialogは引数に項目の数も必要とするのでこのとき一緒に計算している($BROWSE_LIST_NUM).次のポイントはgdialogがユーザが選択した項目(ここではユーザが選択したブラウズするURL)をstderrに出力する点である.このために,コマンドの最後に
2>&1
とすることで,stderrをstdoutにリダイレクトしている.最後にブラウザの起動だが,(私にとっては)ちょっとトリッキーなことをしてみた.ユーザが選択した項目は,gdialogから例えば
"http://hoge.org" "http://fuga.org"
というように,一行で返される.これが$BROWSE_RESULTに格納されるわけだが,
mozilla $BROWSE_RESULT
などとすると,最初のURLが表示されるだけで,二つ目以降のURLは無視される.そこで,関数を新たに作成し,その関数に渡す.
    if [ $? -eq 0 ]
    then
	browse $BROWSE_RESULT;
    fi
if文の中身はgdialogでユーザがOKを押した場合に実行される(キャンセルを押すとgdialogは1を返す).
function browse(){
    while [ "$1" != "" ]
    do
	eval $BROWSE_COMMAND $1 &
	shift 1;
    done
}
このようにshiftを使用することで,$BROWSE_RESULTを一つずつ取り出してそれぞれでブラウザを起動している.
このスクリプトのその他のポイントとしては,
tempfileコマンド
tempfileコマンドで一時ファイルを作成し使用.
BASHの変数展開
${A##*/}は$(basename $A)と等価である.
nkfコマンド
サイトの文字コードに注意する.
こんなもんか.やっぱり大したスクリプトではないな...
なんか出力ではHTMLタグがウザイので暇があったら直したい.そのとき勢いでPerlに移植できればなお良いのだが...あと,gdialogの日本語が化ける.
matsu(C)
Since 2002
Mail to matsu