グローバル変数

AWKの本を読んでいたら、

プログラミング言語AWK

プログラミング言語AWK

  • 作者: A.V.エイホ,P.J.ワインバーガー,B.W.カーニハン,足立高徳
  • 出版社/メーカー: USP研究所
  • 発売日: 2010/01/01
  • メディア: 単行本(ソフトカバー)
  • クリック: 1回
  • この商品を含むブログを見る
本文中に1行を60文字までに整形するプログラムが掲載されていて、AWKグローバル変数のことを知らなかったので、functionの中のlineがどこで定義され、何の値が入っているかわからず理解するのにえらく時間がかかった。
参考)グローバル変数とローカル変数
http://homepage2.nifty.com/mozu/koza/awk_koza/awk_koza_19.html

(list: fmt.awk)

#!/usr/bin/awk -f

/./  { for (i=1; i<=NF; i++) addword($i) }
/^$/ { printline(); print "" }
END  { printline() }

function addword(w){
  if (length(line) + length(w) > 60)
    printline()
  line = line " " w
}

function printline(){
  if (length(line) > 0){
    print substr(line, 2) #先頭の空白を除去する
    line = ""
  }
}


ユーザ定義関数からグローバル変数書き換えてて、有名本なのによくないプログラミングだと思う。小さいプログラムだから問題ないという判断なのかも知れないが。。


そこでユーザ定義関数でグローバル変数を書き換えないようなプログラムを書いてみる。
fmt.awkを、ユーザ定義関数なしで書き直してみる。
(list: fmt2.awk)

#!/usr/bin/awk -f

/./ {
      for(i=1; i<=NF; i++) {
        if( length(line) + length($i) > 60){
          print substr(line,2)
          line = " " $i
        }else{
          line = line " " $i
        }
      }
    }
/^$/{
      print substr(line,2)
      print ""
      line = ""
    }
END {
      print substr(line,2)
    }

fmt.awkと等価ではないような微妙なできばえ。


次は、ユーザ定義関数を使用するが、関数内でグローバル変数を使わないで書いてみる。
(list: fmt3.awk)

#!/usr/bin/awk -f

BEGIN { line = "" }
/./ {
      for(i=1; i<=NF; i++){
        line = addword(line, $i)
      }
    }
/^$/{
      line = printline(line)
      print ""
    }
END {
      printline(line)
    }

function addword(line, w){
  if( length(line) + length(w) > 60 ){
    printline(line)
    return " " w
  }else{
    return line " " w
  }
}

function printline(line){
  if (length(line) > 0){
    print substr(line,2)
  }
  return ""
}

return文をしっかり書いた。これでずっとプログラムの見通しがよくなると思うよ。当たり前のことなんだけど。


実行してみる。

$ more sample.txt
AWK is an interpreted programming language designed for text processing and typically used as a data extraction and reporting tool. It is a standard feature of most Unix-like operating systems.

AWK was created at Bell Labs in the 1970s,[2] and its name is derived from the family names of its authors  Alfred Aho, Peter Weinberger, and Brian Kernighan.
$ ./fmt.awk sample.txt
AWK is an interpreted programming language designed for text
processing and typically used as a data extraction and
reporting tool. It is a standard feature of most Unix-like
operating systems.

AWK was created at Bell Labs in the 1970s,[2] and its name
is derived from the family names of its authors Alfred Aho,
Peter Weinberger, and Brian Kernighan.

$ ./fmt2.awk sample.txt
AWK is an interpreted programming language designed for text
processing and typically used as a data extraction and
reporting tool. It is a standard feature of most Unix-like
operating systems.

AWK was created at Bell Labs in the 1970s,[2] and its name
is derived from the family names of its authors Alfred Aho,
Peter Weinberger, and Brian Kernighan.


参考)プロセス置換機能を使って結果を比較する

$ diff <(./fmt.awk sample.txt ) <(./fmt3.awk sample.txt )
$

http://d.hatena.ne.jp/tigerii/20120826/1345952762