作者: 藤岡和夫
日時: 2008/3/02(09:13)
On Sun, 02 Mar 2008 02:56:51 +0900
davi <davi-1984@...> さんwrote:

> 
> 藤岡和夫さん みなさん  <  こん??は でび です
> 
> On Sat, 01 Mar 2008 09:18:15 +0900
> 藤岡和夫 <kazuf@...> wrote:
> 
> | BEGIN{
> |     FS=","
> | }
> |
> | { titles[$1] }
> | $2 == "著者" { author[$1] = $3 }
> | $2 == "訳者" { trans[$1] = $3 }
> | $2 == "出版社" { pub[$1] = $3 }
> | $2 == "出版年" { year[$1] = $3 }
> |
> | END{
> 以下ry)
> 
> 書き方のことで伺います。
> メイン部分の1個目、{ titles[$1] }で一度閉じていますよね。
> 
> “上の例に限って”考えると、たとえば
> 
> ex.1 ---------------
> 
>  { titles[$1]
>      $2 == "著者" { author[$1] = $3 }
>      $2 == "訳者" { trans[$1] = $3 }
>      $2 == "出版社" { pub[$1] = $3 }
>      $2 == "出版年" { year[$1] = $3 }
>  }
>  ---------------
> 
> ex.2 ---------------
> 
>  { { titles[$1] }
>      $2 == "著者" { author[$1] = $3 }
>      $2 == "訳者" { trans[$1] = $3 }
>      $2 == "出版社" { pub[$1] = $3 }
>      $2 == "出版年" { year[$1] = $3 }
>  }
>  ---------------
> 
> ex.3 ---------------
> 
>  titles[$1];
>      $2 == "著者" { author[$1] = $3 }
>      $2 == "訳者" { trans[$1] = $3 }
>      $2 == "出版社" { pub[$1] = $3 }
>      $2 == "出版年" { year[$1] = $3 }
>  ---------------
> 
> でも通りそうですが、上の例に“限らず”、汎用的に
> 考えるとき、 { } の付け方って、何か規則性というか、
> ハマリを避けるために必要な観点ってありますか?

AWKはSedなどに近い行単位処理指向のフィルター型の言語なんですね。加えて構
造を持ったプログラムを記述できる機能も併せ持っているのでわかりにくい。

BEGINブロックとENDブロックの間のブロックは行毎に処理するループになるので
す。それをご存知ですか。BEGINブロックではループを回すための前提条件を整
え、ENDブロックではループを回した後の処理をするということになります。

だから私が最初に書いたスクリプトは、AWK独特の、

BEGIN{前処理}
条件1{処理1} <- ループの最初の処理
条件2{処理2}
...
条件n{処理n} <- ループの最後の処理
END{後処理}

の基本的な構造を持っています。

ループの中に制御構造を持ち込めば、ループの処理を一つにまとめることができ
ます。二つ目のスクリプトを少し書き直して示します。変えたのは、「else」をif
文に付け加えた制御構造としました。ロジックとしては効率がよくなるはずです
から。

BEGIN {
    FS = ","
}
{
    title = $1
    if ( prtitle != title && count != 0 ){
        printf( "%s,%s,%s,%s,%s\n", prtitle,author,translator,publisher,year )
        author = "";translator = "";publisher = "";year = ""
    }
    if ( $2 == "著者" ) { author = $3 }
    else if ( $2 == "訳者" ) { translator = $3 }
    else if ( $2 == "出版社" ) { publisher = $3 }
    else if ( $2 == "出版年" ) { year = $3 }
    prtitle = title;count++
}
END{
    printf( "%s,%s,%s,%s,%s\n", prtitle,author,translator,publisher,year )
}

Perlで書けば、

前処理
while(<>){
    if(条件1){処理1}
    elsif(条件2){処理2}
    ......
    elsif(条件n){処理n}
}
後処理

と書くのと同じことです。

従って、ブロックの書き方には意味があります。恣意的なものではない。AWKに
ついてはまず二通りの書き方があるということを知る必要があります。AWKの場
合は、BEGIN部だけでスクリプトを書くことができたりします。

藤岡 和夫
kazuf@...
日曜プログラマのひとりごと http://homepage1.nifty.com/kazuf/renewal.html