「Awk」の版間の差分

提供: Wikinote
移動: 案内検索
(Wiki 用に空白を挿入する)
(関数)
 
(同じ利用者による、間の17版が非表示)
行1: 行1:
* 参考 URL
+
手軽さとパワーのバランスが素晴らしい AWK について。
** [http://www.kt.rim.or.jp/~kbk/gawk/gawk_toc.html The GAWK Manual] (2.15.6)
+
 
** [http://www.kt.rim.or.jp/~kbk/gawk-30/index.html AWK Language Programming] (3.0.4)
+
ちなみに、AWK の A は、(オレの好きな) かの有名な Aho-Corasick 法を作った
* 基本構文
+
Aho 氏の A である!K はカーニハン。そりゃいい言語だわな。
  awk [-F sep] 'command' [file ...]
+
 
* 組み込み変数
+
== 参考文献 ==
** FS - フィールドセパレータ
+
* [http://www.gnu.org/software/gawk/manual/gawk.html The GNU Awk User's Guide] (3.1.6) — 本家のマニュアル
** NR - 現レコード数
+
* [http://www.kt.rim.or.jp/~kbk/gawk/gawk_toc.html The GAWK Manual] (2.15.6)
** NF - フィールド数
+
* [http://www.kt.rim.or.jp/~kbk/gawk-30/index.html AWK Language Programming] (3.0.4)
** OFS - 出力フィールドセパレータ (print のカンマ区切りのセパレータ)
+
 
** ORS - 出力レコードセパレータ
+
== 覚え書き ==
* 演算子
+
 
** ~ - マッチしたら真 ($0 ~ /re/)
+
=== コマンド構文 ===
** 他はほぼ C と同じ
+
  awk [-F sep] [-f progfile] [-v name=value] 'program' [file ...]
* 制御構文
+
 
** <code>break</code>, <code>continue</code> - for や while の中で使う
+
* セパレータ (デリミタ) は -F で指定することに注意
** <code>next</code> - 次のレコードへ処理を移す
+
* -f で自作ライブラリを複数取り込める
** <code>exit</code> - 残りのレコードは見ないで処理を中断
+
* -v で変数を渡す
* 配列
+
 
** <code>array[i]</code> - 一次元配列
+
=== 組み込み変数 ===
** <code>array[i,j,k]</code> - 三次元配列
+
* FS ― フィールドセパレータ (デフォルトはスペース)
** <code>array[str]</code> - 連想配列
+
* NR 現レコード数
*** <code>for (x in array) ...</code> ですべてのキーを取り出し可能
+
* NF フィールド数
*** <code>if (str in array) ...</code> でキー str があるかどうか
+
* OFS 出力フィールドセパレータ (print のカンマ区切りのセパレータ; デフォルトはスペース)
*** <code>array[str] = array[str] "hoge"</code> で連結可能
+
* ORS 出力レコードセパレータ (デフォルトは改行)
* その他
+
 
** 変数の初期化は不要
+
=== 演算子 ===
** print $1 $2 で連結出力、カンマ区切りでスペース
+
* ~ ― 正規表現にマッチしたら真 ($0 ~ /re/)
** <code>{ print $0; } = { print; } = </code>
+
他はほぼ C と同じ
** 配列は参照渡し
+
 
** -f program で自作ライブラリを複数取り込める
+
=== 制御構文 ===
** $n (n > 0) を書き換えると、$0 も書き換わる
+
* <code>break</code>, <code>continue</code> for や while の中で使う
 +
* <code>next</code> 次のレコードへ処理を移す
 +
* <code>exit</code> 残りのレコードは見ないで処理を中断 (END の中は実行されるので注意)
 +
 
 +
=== 配列 ===
 +
* <code>array[i]</code> 一次元配列
 +
* <code>array[i,j,k]</code> 三次元配列
 +
* <code>array[str]</code> 連想配列
 +
** <code>for (x in array) { ... }</code> ですべてのキーを取り出し可能
 +
** <code>if (str in array) { ... }</code> でキー str があるかどうか
 +
** <code>array[str] = array[str] "hoge"</code> で連結可能
 +
 
 +
=== 関数 ===
 +
関数定義は function で行う。ローカル変数は以下のように引き数とはスペースで少し離して記載する。
 +
function name (param1, param2,        local) {
 +
      body-of-function
 +
}
 +
 
 +
* 配列は参照渡しになる (関数の中で書き換え可能)
 +
* sub 系の関数の返り値は置換した個数。渡した文字列が in-place で置換されるので注意。
 +
 
 +
=== 文字列 ===
 +
 
 +
* 文字列を単に並べると連結 "hoge" "fuga" → "hogefuga"
 +
* <code>print $1, $2</code> でスペース空けて出力 (区切りは OFS で変更可)
 +
 
 +
=== その他 ===
 +
* 変数の初期化は不要
 +
* <code>{ print $0 } = { print } = </code>
 +
** 要するに、<code>grep hoge = awk /hoge/</code>
 +
* $n (n > 0) を書き換えると、$0 も書き換わる
 +
* $(n) で入力レコードを変数で指定できる。
 +
つまり、以下のように for で回すことが可能。
 +
for (i = 1; i <= NF; i++) {
 +
    print $(i)
 +
}
  
 
== サンプルスクリプト ==
 
== サンプルスクリプト ==
行46: 行81:
 
   }
 
   }
 
ただ、コマンド行はスペースが入らないので注意すること。>自分
 
ただ、コマンド行はスペースが入らないので注意すること。>自分
 +
 +
=== レコード範囲指定 ===
 +
begin を含む行から end を含む行の範囲だけを出力する場合は、以下のように sed と同じように指定する。
 +
$ awk '/begin/,/end/' data
 +
では、その範囲だけ出力しない場合は?これは、next を使う。
 +
$ awk '/begin/,/end/{next} 1' data
 +
最後の 1 が最短の秘訣 ;-)

2011年3月10日 (木) 00:47時点における最新版

手軽さとパワーのバランスが素晴らしい AWK について。

ちなみに、AWK の A は、(オレの好きな) かの有名な Aho-Corasick 法を作った Aho 氏の A である!K はカーニハン。そりゃいい言語だわな。

参考文献

覚え書き

コマンド構文

awk [-F sep] [-f progfile] [-v name=value] 'program' [file ...]
  • セパレータ (デリミタ) は -F で指定することに注意
  • -f で自作ライブラリを複数取り込める
  • -v で変数を渡す

組み込み変数

  • FS ― フィールドセパレータ (デフォルトはスペース)
  • NR ― 現レコード数
  • NF ― フィールド数
  • OFS ― 出力フィールドセパレータ (print のカンマ区切りのセパレータ; デフォルトはスペース)
  • ORS ― 出力レコードセパレータ (デフォルトは改行)

演算子

  • ~ ― 正規表現にマッチしたら真 ($0 ~ /re/)

他はほぼ C と同じ

制御構文

  • break, continue ― for や while の中で使う
  • next ― 次のレコードへ処理を移す
  • exit ― 残りのレコードは見ないで処理を中断 (END の中は実行されるので注意)

配列

  • array[i] ― 一次元配列
  • array[i,j,k] ― 三次元配列
  • array[str] ― 連想配列
    • for (x in array) { ... } ですべてのキーを取り出し可能
    • if (str in array) { ... } でキー str があるかどうか
    • array[str] = array[str] "hoge" で連結可能

関数

関数定義は function で行う。ローカル変数は以下のように引き数とはスペースで少し離して記載する。

function name (param1, param2,         local) {
     body-of-function
}
  • 配列は参照渡しになる (関数の中で書き換え可能)
  • sub 系の関数の返り値は置換した個数。渡した文字列が in-place で置換されるので注意。

文字列

  • 文字列を単に並べると連結 "hoge" "fuga" → "hogefuga"
  • print $1, $2 でスペース空けて出力 (区切りは OFS で変更可)

その他

  • 変数の初期化は不要
  • { print $0 } = { print } =
    • 要するに、grep hoge = awk /hoge/
  • $n (n > 0) を書き換えると、$0 も書き換わる
  • $(n) で入力レコードを変数で指定できる。

つまり、以下のように for で回すことが可能。

for (i = 1; i <= NF; i++) {
    print $(i)
}

サンプルスクリプト

Wiki 用に空白を挿入する

Wiki では、行が空白から始まっていると、以下のように固定幅フォントでタイプした通りに表示される。

ソースや出力結果などは通常これを用いる。

いちいち手作業で空白を入れるのは面倒なので (vim で C-v I はまあ許せるとして) gawk スクリプトにする。これはお手軽。

[hagio@localhost hagi_utils]$ cat addspace.gawk | ./addspace.gawk 
 #!/bin/gawk -f
 {
        print " " $0
 }

ただ、コマンド行はスペースが入らないので注意すること。>自分

レコード範囲指定

begin を含む行から end を含む行の範囲だけを出力する場合は、以下のように sed と同じように指定する。

$ awk '/begin/,/end/' data

では、その範囲だけ出力しない場合は?これは、next を使う。

$ awk '/begin/,/end/{next} 1' data

最後の 1 が最短の秘訣 ;-)