getline < [file]
: [file] として指定したファイルから
現在行の次の行を読みこんでそれを新たな現在行とし $0 等に代入する。
読み込みに成功すると 1, ファイルの最後に達した場合は 0,
読み込みに失敗したら を返す。
fname = "soci-001.html" while(getline < fname){ # $0 に各行が代入される } close(fname)のようにして指定したファイルの各行の処理を、 AWK の通常の入力行に対する処理と同じように行うことができます。
今回は、その行の中から
1/6ページを表示(合計123件) ...のような行を取得すればいいのですが、これを例えば日本語のパターンを使って
$0 ~ /ページを表示/
のようにすることもできなくはありませんが、
このようにすると漢字コード
(スクリプトの漢字コード、入力ファイルの漢字コード、および使用している
AWK が対応している漢字コード)
によってうまくマッチできないことがありますので注意が必要です7。
調べてみると、この一覧の HTML ファイルでは ``1/6'' のような文字列が行頭にあるのはこの部分だけのようなので 以下のようなパターンを使って取り出すことにします。
$0 ~ /^[1-9][0-9]*\/[1-9]/
この正規表現は、
を意味します。[0-9]
: 0 から 9 までの数字 1 文字
[0-9]*
: 0 から 9 までの数字 0 文字以上の繰り返し
[1-9][0-9]*
: 0 以外で始まる 1 文字以上の数字文字列
^[1-9][0-9]*\/[1-9]
: 行頭が 0 以外で始まる数字列 + '/' + 0 以外の数字
この行の先頭部分から、 '/' 以降の分母の部分を match() と substr() を使って 取り出します。
match($0,"/\/[1-9][0-9]*/) pages = substr($0,RSTART+1,RLENGTH-1)+0この substr() の引数ですが、 RSTART+1 は '/' に続く数字列の先頭部分を意味しますし、 '/' を取り除くためにマッチした長さから 1 を引いた RLENGTH-1 を切り出しています。
また、最後の ``+0'' は、変数 pages を数字化するためにつけています。 通常、substr() で切り取ったものは文字列として返されますから、 そのままだと文字列として変数に代入されますが、 ``+0'' という数字演算をつけることで、 その文字列が数字として評価されて代入されることになります。
AWK では、文字列と数字の明示的な区別がなく、
評価されるところで適宜自動的な変換が行われるので、
この変数を次に使用するところが数字演算の中などであれば
その時に自然に数字に変換されて使われるので問題はないのですが、
例えば次に使用するところが ``=='' や ``>
'' などの
比較演算だとしたら、
これらの演算は文字列も数字も受けつけて、
それぞれで別の評価をしてしまいますので
文字列のままと見なされると誤動作の原因となりえます。
よって、文字列を確実に数字にしたい場合は ``+0'' をつけるのが AWK の常套手段となっています。 逆に数字を確実に文字列にしたい場合は
n = n ""
のように空文字列を連結します8。
以上をまとめると、以下のようにすれば pages を取得できることになります。
##### pages の取得 ##### pages = 0 fname = "soci-001.html" while(getline < fname){ if($0 ~ /^[1-9][0-9]*\/[1-9]/){ match($0,/\/[1-9][0-9]*/) pages = substr($0,RSTART+1,RLENGTH-1)+0 break } } close(fname)