[3] では、URL リストファイルにコメントの記述を許すようにし、 それにより URL リストファイルから 各 URL エントリを削除、追加することを容易にしました。 ところが、wwwcheck2.csh を行うことを考えると、 現在の URL リストファイルには問題があります。 3 節の wwwcheck1.csh では、 取得した HTML ファイルを [n ].html という名前で保存しますが、 この n は、「URL リストファイルの先頭から何番目」 であるかという数字になっています。
しかしそれだと、上の方の URL エントリをコメントアウトして削除した場合、 それより下のエントリに対する n の数字が、 次回の取得ではずれてしまうことになります。 例えば、URL リストファイルが、
http://www.iee.niit.ac.jp/である場合は、 http://www.yahoo.co.jp/ は 2.html として保存されますが、 それを
http://www.yahoo.co.jp/
# http://www.iee.niit.ac.jp/のように 1 行目をコメントアウトして削除した場合は、 3 節の wwwcheck1.csh では、 http://www.yahoo.co.jp/ は 1.html として保存されてしまいます。 wwwcheck1.csh では、これ自体は問題はありませんが、 wwwcheck2.csh で古いものと比較する場合にファイル名のずれは問題となり、 正しく違いを調べることができなくなります。
http://www.yahoo.co.jp/
よって、各 URL エントリと保存するファイル名の間に、 URL リストファイルの更新 (URL エントリの追加や削除) に左右されない しっかりした対応をつける必要があります。 これを行うには、例えば次のような 2 つの方法が考えられます。
url nameの形式で書き、その url の HTML を name.html という名前で保存することとする。 そしてこの name の部分は重複しないようにする。 この場合は、URL エントリの削除や追加、並べ換えなども任意に行える。
URL リストファイルをこのようにすると、 wwwcheck1.csh ではそこから各行の 1 列目の要素と 2 列目の要素を別々に読み出す、という作業が必要になります。 これを行うのにも、例えばリスト変数を利用する方法と、 AWK を利用する方法があります。
リスト変数を利用して 1 列目、2 列目を取得する方法とは、 以下のようにするやり方です:
set urldata = ( `grep "^#" $urllistf` )最初のリスト変数 urldata には、 URL リストファイルのコメント行以外の各行の要素が入るので、
while ( $#urldata > 1 )
set url = "$urldata[1]"
set name = "$urldata[2]"
$wget "$url" > $datad/$name.html
shift urldata
shift urldata
end
( [1 行目の url] [1 行目の name] [2 行目の url] [2 行目の name] ...)のようになります。よってそれを先頭から 2 つずつ ($urldata[1] と $urldata[2]) 取り出していけばいいことになります。 上のコードでは最後に shift の行が 2 行ありますが、 shift はリスト変数の先頭の要素を削除するので、 これを 2 回行うことで先頭の要素を 2 つ取り除くことになります。
しかしこのリスト変数を用いる方法では、 ある行の URL エントリで name 部分を書き忘れてしまった場合は、 そこから先はずれてしまって問題が起きてしまいます。 例えば、URL リストファイルが、
http://www.iee.niit.ac.jpのように 1 行目に name 部分を忘れてしまった場合、 リスト変数 urldata の内容は
http://www.yahoo.co.jp yahoo
( "http://www.iee.niit.ac.jp" "http://www.yahoo.co.jp" yahoo )となるので、最初の実行で
url = ``http://www.iee.niit.ac.jp''となってしまうことになります。 これを防ぐには、 各行に 2 列ずつのエントリが書かれていることを確認するといいのですが、 それにはやはり AWK などが必要になります。
name = ``http://www.yahoo.co.jp''
今度は、その AWK を使う方法を紹介しましょう。 AWK は、非常に高機能なフィルタ (プログラム言語) ですが、 ここで使用するのは、
AWK でファイルのコメント行以外の行の 1 列目、2 列目のみを出力させるには、 それぞれ以下のようにすればできます:
もしコメント以外の行で 1 列しかデータが含まれない行があれば、 上の 1. と 2. では、必ず 1. の方の出力する要素の個数が多くなります。 3 列以上の列を持つ行や、 列を持たない行 (空行) を不正な行と見なさないことにするなら、 上の出力の要素の個数を比較することで、 不正な行があるかないかを判別できます。 1., 2. の出力をそれぞれリスト変数にすればそのような判別が行えます:
set urldata = ( `awk '!/^#/{print $1}' $urllistf` )後は、この 2 つのリスト変数の要素をひとつずつ使っていけばいいわけです。
set namedata = ( `awk '!/^#/{print $2}' $urllistf` )
if ( $#urldata == 0 || $#urldata != $#namedata ) then
echo "$urllistf に不正な行が存在するようです。"
exit
endif
while ( $#urldata > 0 )なお、shift を利用すると、 この while 文が終わったときにリスト変数の要素がなくなってしまいますから、 もしその後で同じリスト変数を使用する場合は、 shift を使わずに行う必要があります (今回は必要ありません):
set url = "$urldata[1]"
set name = "$namedata[1]"
$wget "$url" > $datad/$name.html
shift urldata
shift namedata
end
set j = 1これだと、参照する添え字変数 j の値が増えるだけで、 リスト変数の内容は変化しません。 なお、この while 文は、最初に j を 1 とし、 while ブロックの最後で j の値を一つ増やしていて、 j が $#urldata に達するまでのループなので、 丁度 C 言語での for 文に相当します。
while ( $j <= $#urldata )
set url = "$urldata[$j]"
set name = "$namedata[$j]"
$wget "$url" > $datad/$name.html
@ j ++
end
竹野茂治@新潟工科大学