The AWK˜plus Language Specification
AWK~plus
The AWK˜plus Programming Language は、
- プログラム言語AWK (The AWK Programming Language) 仕様と GNU GAWK の主要な拡張機能の実装。
- アトミック変数とスレッドセーフな関数オブジェクトによる並行処理プログラミングのサポート。
- 動的・静的型付け可能な、Apache Groovy との融合による広い守備範囲。
などの特徴を持つ 次世代スクリプト実行環境です。
|
|
AWK スクリプトは、パターンとアクションおよびオプションの関数定義からなる。
- package パッケージ指定 (* Compilerで有効 *)
- import (* Interpreterでは、'*' 指定は、不可 *)
- val グローバル定数 (クラス変数)
- var グローバル変数
- パターン { アクション }
- function 関数定義
- function インライン関数定義
パターンは以下のとおり。
- BEGIN (* 他のパターンとの組み合わせは不可 *)
- END (* 他のパターンとの組み合わせは不可 *)
- Expression
- /正規表現/
- パターン && パターン
- パターン || パターン
- ! パターン
- ( パターン )
- パターン , パターン (* 他のパターンとの組み合わせは不可 *)
- 空のパターン
アクションは以下のとおり。
- val ローカル定数
- var ローカル変数
- function ローカル関数定義
- break
- continue
- delete Array[ '[' Expression ']' ]
- do Statements while ( Expression )
- exit [ Expression ]
- (* 式の値が 0以外の場合は、System.exit() で shellへの復帰値を設定する。 制御の流れを変更する目的で使用する場合(BEGINからENDへの遷移など)は、exit 0 ('0' の場合は、System.exit を発行しない) の利用を推奨 *)
- Expression
- if ( Expression ) Statements [ else Statements ]
- 入出力文
- for ( Expression; Expression; Expression ) Statements
- for (変数 in Arr) Statements (* Arr は、配列 または、イテレータ *)
- next
- nextfile
- new クラス名 ([ パラメータ ])
- return [ Expression ]
- throw スローアブル
- try { Statements
- [ } catch (スローアブル [|...] 変数名) { Statements
- [ } finally Statements ]
- }
- while ( Expression ) Statements
- { Statementss }
- switch ( Expression ) { case Expression or パターン: Statements } [ default: Statements ]
コメントは、一般敵に利用されている形式をサポートしており AWK と C スタイルのコメントを受け付ける。
# (* AWKスタイル行コメント *)
// (* C++スタイル行コメント *)
/* (* Cスタイルコメント *) */
アノテーションは、IDE・コンパイラに対する指示で、一般的に利用されている形態をサポートしている。
(ただし、AWK˜Plusには、Class 定義文が無いため下記に述べる制限事項がある)
- 記述位置: クラスAnnotationは、importの後ろ、グローバル(Class)変数(var/val)の前に記述。 BEGIN、MAIN、END、function(インライン関数を含む)ブロックの前 (コメントとの順序は問わない。関数仮引数に記述する機能は無い)
- 制限事項: グローバル変数を記述した場合は、制限無し。
そうでない場合は、クラスAnnotationを一つだけ記述するのが必須条件 (2つ以上指定すると、勝手に次のブロックに付加される) その他の場所での制限は無い。
Note: サンプル: sample/T4Closure.awk, T7Fibonacci.awk 参照。
数値は、数値区切り文字 ('_') を含む 下記の形式で指定する。
0 [Xx] [0-9A-Fa-f_]+ (* 16 進数 *)
0 [Bb] [01_]+ (* 2 進数 *)
([0-9][0-9_]*[.]?[0-9_]*|[.][0-9_])+([eE][+-]?[0-9_]+)?(* 10 進数 *)
文字列は、下記の形式をサポートしており 目的に応じたスタイルでの記述が可能である。
" (* 文字列リテラル *) "
' (* HTMLスタイル *) '
""" (* マルチライン文字列 (ヒアドキュメント) *) """
/ (* 正規表現 *) /
Note: マルチライン文字列は、右端に'\'を指定した場合は、改行しない。 また左端に'|'を指定した場合は、'|'までの空白を削除する。
Note: 正規表現を文字列として扱うことにより (本来は正規表現形式での指定が有効でない場所での使用において) 直感適な記述が可能になった。
ex. FS="regexp" -> FS=/regexp/
ex. FS = "[ ]"
は、FS = /[ ]/
と記述可能
変数定義は以下のとおり。
val 変数名 [ : タイプ ] = Expression
(* 変更不可能な変数で、プリミティブに対応したオブジェクトを生成する。 また Groovy は、セッターを生成しない。
var 変数名 [ : タイプ ] = Expression (* 変更可能な変数で、タイプがプリミティブでない場合は、Atomic 変数をを生成する *)
関数定義の宣言の各要素は省略可能でタイプ指定が追加された。
関数定義 = 'function' 名前 ['(' { 仮引数 [':' タイプ] } ')' '(' { ローカル変数 [':' タイプ] } ')' ] [':' 戻り値タイプ] ( '{' 文 '}' | ';' ) ;
宣言要素を省略した場合の意味は以下のとおり。
関数定義 = 'function' 名前 '(' { 仮引数 } { ローカル変数 } ')' '{' 文 '}' (* AWK標準スタイル *)
| 'function' 名前 '(' { 仮引数 } ')' '(' { ローカル変数 } ')' '{' 文 '}' (* ローカル変数を()で明示的に宣言 *)
| 'function' 名前 '{' 文 '}' (* 仮引数とローカル変数宣言なし *)
| 'function' 名前 ['(' { 仮引数 } ')'] ';' (* 関数プロトタイプ宣言 *)
| 'function' '{' 文 '}' (* 無名関数 *)
;
関数(メソド)呼び出しは以下のとおり。
関数呼び出し = 名前 ['(' Expression { ',' Expression } ')'] ;
Note: 関数呼び出しパラメータが空の場合の '()' は省略可能であり 関数呼び出しとプロパティ参照の区別はない。
Note: パラメータを区切る ',' は、')(' で置き換え可能であり 関数型言語でのカリー化 (Currying) 記述が可能、 さらに '(' ')' は、'{' '}'に置き換え可能。
fun(a, b); fun(a)(b)
# AWK仕様で'('の前に空白は記述不可 (* 文字列結合と競合 *)
fun(a) {b}
# 独自構文に似せた呼び出しが可能
関数オブジェクトは他の関数と同じように呼び出せるオブジェクトで、 apply メソドが呼び出されたときに実行される。
(クロージャ以外の一般関数(メソド)を関数オブジェクト化したもので、ダックタイピング、リスナー実装、スレッド生成などに利用する)
関数オブジェクト = '.関数名' ;
関数オブジェクト = '..関数名' ; # スレッドセーフな関数オブジェクト
function calc(x: Function) { return x.apply } # 関数を関数オブジェクトとして呼び出すためのコンテナ
function add(a, b) { return a + b }
print calc(.add(1, 2)) # 関数オブジェクト呼び出し
Note: サンプル: sample/Atomic2.awk 参照。
インライン関数が、親のスコープ(エンクロージャ)を参照している場合に、Groovy-Closure に展開される。
Groovy-Closure には、Annotation を付与出来ないことに注意。
また、関数オブジェクト(Function object)機能を使用する場合には、パラメータ渡しにして関数をルートに移動させる必要がある。
Note: サンプル: sample/T4Closure.awk 参照。
組み込み変数は以下のとおりで GNU AWKの主要な拡張機能をサポートする。
- ARGC
- ARGV の要素数
- ARGIND
- 配列 ARGV のインデックス (現在処理中のファイル名が格納されている要素を指す)
- ARGV
- コマンド行引数配列 (添字 1 より格納され AWK へのオプションは含まない)
- ARGV[0] の内容は不定。 AWK(C言語インターフェイス) では実行プログラム名が格納されるが Java にはその概念はない
- BINMODE
- 入出力においてバイナリモード を制御 (Cygwin における行末の改行 "\n", "\r\n" 対策に相当)
- CONVFMT
- 数値から文字列への変換書式 (既定値は、%.6g)
- ENVIRON
- 起動時の環境変数のコピー配列
- ERRNO
- 入出力例外の理由を表わす文字 列
- FIELDWIDTHS
- 固定長レコードを入力するためのフィールド長リスト (2byte コードでは問題あり)
- FILENAME
- 現在の入力ファイル名
- FNR
- 現在の入力ファイルから入力したレコード数
- FS
- 入力フィールドセパレータで 正規表現文字列 を受け付ける (既定値は空白で 空白 と TAB にマッチする /[ \t]+/)
- IGNORECASE
- 文字列比較と正規表現マッチングで英大小文字を区別 (既定値は、0 て英大小文字を区別する)
- LINT
- コマンドラインオプション "--lint" の有無をアプリで制御
- NF
- 現在の入力レコードのフィールド数
- NR
- 現在までに入力したレコード数の合計
- OFMT
- 数値の出力書式 (既定値は、%.6g)
- OFS
- 出力フィールドセパレータ (既定値は空白)
- ORS
- 出力レコードセパレータ (既定値は、プラットフォーム 依存の改行 "\n", "\r" または、"\r\n")
(既定値は、デファクトスタンダードの改行 "\n")
- PROCINFO
- 主にプロセス関連の拡張機能 ("/dev/pid", "/dev/ppid"など) を制御するための配列
- RLENGTH
- match で正規表現にマッチした文字列の長さ
- RS
- 入力レコードセパレータで "正規表現文字列" を受け付ける (既定値は改行)
- RSTART
- match で正規表現にマッチした文字列の開始位置
- RT
- RS にマッチし入力レコードセパレータとなった入力テキスト
- SUBSEP
- 多次元配列の添字区切り文字 (既定値は、'\034')
- TEXTDOMAIN
- GNU AWK 固有機能で国際化に使用
以下の 特殊ファイル名をファイル名として指定できる。
- "/dev/stdin"
- 標準入力 (ファイル記述子 0)
- "/dev/stdout"
- 標準出力 (ファイル記述子 1)
- "/dev/stderr"
- 標準エラー出力 (ファイル記述子 2)
- "/dev/null"
- NULL (ビットバケツ bit bucket)
- "/dev/fd/N"
- ファイル記述子 N に結び付けられたファイル (/dev/stdin, /dev/stdout, /dev/stderr... の実体)
- "/inet/PROTOCOL/LOCAL-PORT/REMOTE-HOST/REMOTE-PORT [ /接続タイムアウト(秒) ] [ /#文字コードセット ]"
-
INET通信
- TCP/IP サーバソケット通信: "inet://tcp/LOCAL-PORT/0/0"
- TCP/IP クライアントソケット通信: "inet://tcp/0/REMOTE-HOST/REMOTE-PORT"
- UDP ローカルソケット通信: "inet://udp/LOCAL-PORT/0/0"
- UDP リモートソケット通信: "inet://udp/0/REMOTE-HOST/REMOTE-PORT"
- "jdbc:SUBPROTOCOL:SUBNAME [ ドライバパラメータ ... ] [ ;; SQL文 ]"
-
- jdbc: この URL が JDBC URL であることを表すスキーム名
- SUBPROTOCOL: サブプロトコル (ドライバを識別する文字列)
- SUBNAME: 接続先のホスト、データベース名称およびドライバオプション
- ;; SQL文: 接続時に実行する SQL文 (オプション)
- "http:// <url> [ #<文字コードセット> ]"
- Web 上のリソースへのポインタを表すURL (入力専用、文字コードの既定値は`utf-8`)
- "file:/// <パス> [ #<文字コードセット> ]"
- ローカルファイルを表すURL (入出力)
入出力ステートメントと関数は以下のとおり。
- close([ Expression ])
- ファイル名を省略した場合は、開いているストリームを全て閉じる
- close(file , how)
- 双方向パイプを閉じる
- fflush([ file | "" ])
- 出力バッファをフラッシュする、 ファイル名が空白("") のときは全ての出力ファイルを、 ファイル名を省略した場合は標準出力および標準エラー出力をフラッシュする
- getline [ var ] [ <, |& file ]
- 次のレコードを var (省略時は、$0) に読む (リダイレクト指定は、<, |, |&) (* この関数は、文または関数として振舞う *)
- next
- 現在のレコードの処理を終了して次のレコードの処理を開始する
- nextfile
- 現在の入力ファイルの処理を終了して次の入力ファイルを読む
- print [ Expression ... ] [ > file ]
- 式の値 (省略時は、$0 ) を出力する (リダイレクト指定は、>, >>, |, |&)
出力文字列中の "\n" は、ORS に変換して出力する (* この関数は、文または関数として振舞う *)
- printf format [ , Expression ... ] [ > file ]
- 書式付き出力 (リダイレクト指定は、>, >>, |, |&) (* この関数は、文または関数として振舞う *)
- system(command [redirect])
-
コマンドを実行して終了ステータスを返す
リダイレクト (redirect) 指定は以下のとおり
- 1>&2 標準出力を標準エラーに出力
- 2>&1 標準エラーを標準出力に出力
- >[>]file ファイルに出力
Note: "|&" は双方向パイプで、 INET 通信で使用する。 (ex. "inet://..." |& getline)
Note: AWKは、 ファイル名を明示して存在しないファイルから入力した場合にエラーとしない仕様であるが エラーとする。 (この機能が必要な場合は、 try catch を使用すること)
数値関数は以下のとおり。
- abs(x)
- x の絶対値
- atan2(x,y)
- x/y のアークタンジェント
- cos(x)
- x の余弦
- exp(x)
- 自然対数の底 e の x 乗
- int(x)
- 小数点以下を切り捨てた整数値 (他 に double, float, long もある)
- log(x)
- x の自然対数
- sin(x)
- x の正弦
- sqrt(x)
- x の正の平方根
- rand()
- 0 以上 1 未満の浮動小数点数の擬似乱数を返す
- srand([ x ])
- x を種として乱数を生成、 x 省略時は直前の種を返す
文字列関数は以下のとおり。
- asort(source [ , dest ])
- source 配列の要素を IGNORECASE に基いて ソート。 dest (または、source) に出力し要素数を返す (出力配列の添字は、1 からの連番)
- asorti(source [ , dest ])
- source 配列の添字を IGNORECASE に基いて ソート。 〃
- index(in, find)
- 文字列 in の中で文字列 find が出てくる最初の位置を返す
- length([ string ])
- string 中の文字数 (配列を指定した場合は、要素数)
- match(string, regexp)
- 正規表現 regexp にマッチする string の最左、最長の文字列位置を返す
- match(string, regexp ,array)
- array はマッチした string の部分文字列配列を取得するための拡張引数
- split(string, array [ , fieldsep ])
- string を fieldsep によって分割し分割された結果を array に格納し要素数を返す
- sprintf(format [ , Expression ... ])
- printf がその引数を渡されたときに出力するであろう文字列を返す
- strtonum(string)
- string を検査してその値を返す (string が'0'で始まる場合は、8進数値, '0x'もしくは'0X'で始まる場合は、16進数値)
- sub(regexp, replacement [ , target ])
- 正規表現 regexp でターゲット文字列 target を replacement で置換し置換数を返す
ターゲットが省略された場合は、$0 が使われる
置換文字列 replacement 中の '&' は、適合文字列に置き換えられる。 また '\&' でアンパサンドそのものを生成する
置換文字列で '\n' (n は、1 から 9 の数字) を指定することにより 正規表現にマッチした n 番目のグループを参照する
- gsub(regexp, replacement [ , target ])
- 正規表現 regexp でターゲット文字列 target を replacement で一括置換し置換数を返す
- gensub(regexp, replacement, how [ , target ])
- 正規表現 regexp でターゲット文字列 target を replacement で how に基いて置換し置換した文字列を返す
- substr(string, start [ , length ])
- 文字列 string の start 番目の文字から始まる長さ length 文字の部分文字列を返す
- tolower(string)
- 大文字をすべて小文字に変換した文字列を返す
- toupper(string)
- 小文字をすべて大文字に変換した文字列を返す
ビット演算子は、以下のとおり。
- x & y
- ビット積 (AND) を返す
- x | y
- ビット和 (OR) を返す
- x ^ y
- 排他的ビット和 (XOR) を返す
- ~x
- x の各ビットを反転 (NOT) して返す
- x << count
- x を count ビット左にシフトした値を返す
- x >> count
- x を count ビット右に0を充填してシフトした値を返す
- x >>> count
- x を count ビット右に符号 bit を充填してシフトした値を返す
時間関数は以下のとおり。
- systime()
- 基準時点 (1970/01/01 00:00:00 UTC,) からの経過時間(秒)を返す
- mktime(datespec)
- 日付時刻を表す文字列をタイムスタンプに変換して返す
- java.text.DateFormat を実装。 引数は、"2007/02/28 00:00:00" など
- strftime([ format [ , timestamp ] ])
- 指定したタイムスタンプ (省略時は現在時刻) を日付時刻を表す文字列に変換して返す
format は、java.text.SimpleDateFormat 形式で指定
プラットフォーム非依存とするために以下の (system) コマンドを抱え込んでいる。
- cat [オプション]... [ファイル]...
- ファイルまたは標準入力を結合し、標準出力へ書き出す
-n 全ての行の出力に行番号を付加
-b 空でない行の出力に行番号を付加
-s 連続した空行を圧縮する
-T TAB文字を`^I'で表示
- date [+'フォーマット']
- 現在時刻を有効なFORMATで表示する (Thu Sep 29 11:13:18 JST 2011 など)
+フォーマット指定は、java.text.SimpleDateFormat 参照
- echo [オプション]... [文字列]
-
文字列を表示する
-n 文字列の最後で改行しない
-e 文字列中のエスケープ文字を有効にする
-E エスケープ文字を処理しない (-e の逆)
\a alert (BEL)
\b backspace
\f form feed
\n new line
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\uFEFF UNICODE
\xFF Hex decimal
\0777 Octal decimal
- exit 終了値
- コマンドの終了値を設定する
- sleep 時間
- 指定した時間停止する (時間は秒単位で指定し少数点形式も可能)
- sort [オプション]... [ファイル]...
- 文字列をソートする
-b 各行の比較の際に、行頭の空白を無視する
-d アルファベット、数字、空白以外を無視する
-f アルファベットの大文字と小文字を区別しない
-g 数値として比較する
-n 先頭の文字列 (空白が前置されていても良い) を数値文字列として比較する
-r 比較の結果を逆順にする
-tSEP 指定した文字をフィールド区切りとして使用する
-u 同一内容の行は1度しか表示しない
+POS1[-POS2] POS1 から POS2 (POS2 省略時は行末) までが ソートキーとなり、フィールド位置は、0 から始まる
-POS2 end it at POS2(default end of line)
-kPOS1[,POS2] ソートキーを指定する別法。 フィールドと文字位置は、1 から始まる
式は、以下の演算子を用いて結合してもよい。
代入 |
= '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '**='
| '<<=' (* 左シフト代入 *)
| '>>=' (* 符号なし右シフト代入 *)
| '`&=' (* ビットごとのAND代入 *)
| '`|=' (* ビットごとのOR代入 *)
| '`^=' (* ビットごとのXOR代入 *)
| '`~=' (* ビットごとの補数代入 *)
; |
条件 |
= 論理式 '?' 式 ':' 式 ; |
論理和 |
= '||' ; |
論理積 |
= '&&' ; |
存在確認 |
= 式 'in' 配列名 (* 配列要素の存在確認 *)
| 関数オブジェクト 'in' オブジェクト ; (* メソド、プロパティの存在確認 *)
|
代入互換性 |
= 式 'is' クラス名 ; (* instanceof *) |
照合 |
= 式 '~' 正規表現 (* 適合 *)
| 式 '!~' 正規表現 (* 非適合 *)
; |
関係 |
= '<' | '<=' | '>' | '>=' | '!=' | '=='
| '===' | '!==' (* 等価演算子 (Javaの '==') see. sample/T6Mutable.awk *)
; |
連接 |
(* 文字列の結合、空の演算子 *) |
和、差 |
= '+' | '-' ; |
積、商、剰余 |
= '*' | '/' | '%' ; |
単項和と差 |
= '+' | '-' ; |
論理否定 |
= '!' ; |
累乗 |
= '**' ; |
インクリメント、デクリメント |
= '++' | '--' ; |
関数オブジェクト |
= '.|..' 関数呼び出し ; (* '..' はコンカレント呼び出し *) |
欄 |
= '$' ; |
グループ化 |
= '(' 式 ')' ; |
非同期計算スレッド (Futureタスク) を支援する関数は以下のとおり。
- Barrier(n: int)
- n 個のスレッド (パーティの参加者) が共通のバリアーポイントに達するまで待機する 同期化支援機能を返す
- Future(x: Function)
- 取り消し可能な非同期計算スレッド (Futureタスク) を開始して Futureタスクを返す
- Cancel(a: Future)
- Futureタスクの実行の取り消しを試みる
- Join(a: Barrier)
- バリアーポイントで待ち合わせる
- Join(a: Future)
- Futureタスクの終了を待機して 計算結果を返す
- isAlive(a: Future)
- Futureタスクが生存しているかどうかを返す
並行プログラミングを支援する関数は以下のとおり。
- Channel()
- スレッド間の通信に利用する リンクノードに基づく任意のバウンド形式の ブロッキング両端キューを返す
- Range(start: int, end: int, step: int*)
- 開始、終了、増分値で指定された 範囲を表す 整数値イテレータを返す
- Sleep(second: Number)
- 現在実行中のスレッドを second秒 一時的にスリープする
基本的な型は以下のとおり。 (通常は、型推論を使用し、性能重視の場合は、プリミテブ型を使用する)
Boolean |
ブール型 (boolean) |
Number |
数値型の総称 |
Integer |
短整数型の総称 (int) |
Double |
実数または長整数型の総称 (double, float, long) |
String |
文字列型の総称 (String, CharSequence) |
Map |
連想配列 (AtomicMap) |
List |
ArrayList (AtomicArray) |
Function |
関数オブジェクト |
Reference |
参照変数 |
Void |
関数の戻り値、無し. |
Object |
コンパイラに型推論を依頼する. |