次へ: 5 必要な部分文字列の取得 上へ: AWK による HTML ファイルの整形 前へ: 3 Yahoo! ニュース記事の構造 (PDF ファイル: awkhtml.pdf)


4 目標となる行の取り出し

この節では、3 節で紹介した必要な部分のうち、 例えば 1. の <title>$\sim$</title> の行を取得する方法について 考えてみます。

3 節で見たように、 <title>$\sim$</title> 部分は複数行でできているようです。 このサンプルでは 3 行ですが、 実際にはもっと長かったり短かったりするかもしれません。 <title>, </title> タグ自体も サンプルではそれらが単独の行になっていますが、 実際には <title> の次に改行なしですぐに内容の文が続いたり、 </title> の後ろに何らかの文字が続いているかもしれません。

一方で AWK は基本的に行単位のフィルタで、 入力を 1 行ずつ読み込んで処理する形になっています。 よって、このように処理の単位が複数行である場合は、 以下のような 2 種類の処理の方法が考えられます。

  1. 対象となる部分の先頭の行を読みこんだら、 getline を使ってその対象部分の終りまでを 一気に読み込んでしまって処理を行う
  2. 対象となる部分の先頭の行を読みこんだら、 現在その対象の部分内であるという目印 (フラグ) をつけ、 終りの行に達したらその目印をはずしてその処理を行う

getline は新たな行を取得するときに使います。

これらを AWK の (疑似) コードで書くとそれぞれ以下のようになります。

現在の入力行全体は $0 で、 文字列が正規表現にマッチするかどうかは ~, !~ で調べます。

正規表現は / / で囲んで指定します。 正規表現のパターン内に / を書く場合は、 区切り記号と区別するために \ をつけて \/ と書きます (エスケープ)。

上のサンプルでは、配列に各行を保存していますが、または <title>$\sim$</title> を一つの文字列として保存する手もあります。 その場合は、上の ``h[++N]=$0'' の代わりに、例えば ``str = str $0'' のようにします。 AWK では 2 つの文字列を並べると、それで文字列の連結を意味します。

また、getline を使う場合は、 万が一 </title> を含む行が見つからなかった場合を考えて (その場合最後の行まで一気に取得してしまう)、 単なる getline の代わりに

  if(getline<=0){ errorexit=1; exit }
のようにしておくといいかもしれません。 exit は、入力の読み込みをやめ、 END ブロックがあればそこにジャンプするだけなので、 その前に errorexit などのような変数 (変数名は何でも構いません) をセットすることで、END ブロックの先頭に
  END{
    if(errorexit){
         printf "エラー発生 (code = %d)\n",errorexit > "/dev/stderr"
         exit
    }
    ....
と書いておけば END ブロックの他の処理を実行せずに エラー終了することができます。 なお、この printf の後ろについている「> "/dev/stderr"」は 本来は Unix に由来する記法で、 標準エラー出力への出力を行うための書き方です。 こう書けば AWK の出力をファイルなどにリダイレクトしても、 この出力はリダイレクトされずに画面に表示されます。


次へ: 5 必要な部分文字列の取得 上へ: AWK による HTML ファイルの整形 前へ: 3 Yahoo! ニュース記事の構造
竹野茂治@新潟工科大学
2006年8月14日