The AWK~plus Language Specification
AWK~plus
The AWK~plus Programming Language は、
- プログラム言語AWK (The AWK Programming
Language) 仕様と GNU
GAWK の主要な拡張機能の実装
- 型推論と 関数型プログラミングによるシンプルな外観
- 言語レベルでの ロックフリーでスレッドセーフな並列プログラミングのサポート
- 動的型付 (インタプリタ) と 静的型付け (コンパイラ) をハイブリッドでサポートする型システム
などの特徴を持つ 次世代スクリプト実行環境です。 |
|
AWK プログラム (スクリプト) は パターンとアクションおよびオプションの関数定義からなる。
- package パッケージ指定
(* Compilerで有効 *)
- import
(* Nonimplement *)
- extends 継承クラス指定
(* Compilerで有効、The Scala形式で指定 *)
- var グローバル変数定義
- val グローバル変数定義
- パターン { アクション }
- function 関数定義
パターンは以下のとおり。
- BEGIN (*
他のパターンとの組み合わせは不可 *)
- END (*
他のパターンとの組み合わせは不可 *)
- Expression
- /正規表現/
- パターン
&& パターン
- パターン || パターン
- ! パターン
- ( パターン )
- パターン , パターン
(* 他のパターンとの組み合わせは不可 *)
- 空のパターン
アクションは以下のとおり。
- var ローカル変数定義
- val ローカル変数定義
- function ローカル関数定義
- break
- continue
- delete Array[
'[' Expression ']' ]
- do Statement
while ( Expression )
- exit [ Expression
]
- (*
式の値が 0以外の場合は System.exit() で shellへの復帰値を設定する
(JavaVM を終了) 制御の流れを変更する目的で使用する場合(BEGINからENDへの遷移など)は exit 0
('0' の場合は exit を発行しない)
の利用を推奨 *)
- Expression
- if ( Expression
) Statement [ else Statement ]
- 入出力文
- for ( Expression;
Expression; Expression ) Statement
- for (変数 in Arr) Statement
(* Arr は 配列 または イテレータ *)
- next
- nextfile
- new クラス名 [ : タ
イプ ] [ パラメータ
]
- return [ Expression
]
- throw インスタンス
- try Statement
{ catch 変数名
: クラス名 Statement }
[ catch [ 変数名
]
Statement ] (* else の場合 *)
[ finally Statement
]
- while ( Expression
) Statement
- { Statements }
- switch ( Expression ) { case
Expression or パターン: Statement } [
default: Statement ]
コメントは
一般敵に利用されている形式をサポートしており AWK と C スタイルのコメントを受け付ける。
# (* AWKスタイル行コメント *)
// (* C++スタイル行コメント *)
/* (* Cスタイルコメント *) */
数値は 数値区切り文字 ('_') を含む 下記の形式で指定する。
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:
正規表現を文字列として扱うことにより (本来は正規表現が有効でない場所での使用において) 直感適な記述が可能になった。
FS=/[ ]/;
# FSに正規表現"[ ]"を代入、GNU AWKでは FS=$0~/[ ]/;
と解釈される
変数定義は以下のとおり。
val 変数名 [ : タイプ ] = Expression
(*
変更不可能な変数で オブジェクトまたは プリミティブを定義する。
タイプ指定は型推論により不要であり キャストが必要な場合に指定すればよい
*)
var 変数名 [ : タイプ ] = Expression
(*
変更可能な変数で、 タイプ指定により効率的なコードを生成する *)
関数定義の宣言の各要素は省略可能でタイプ指定が追加された。
関数定義 = 'function' 名前 ['('
{
仮引数 [':' タイプ] } ')' '(' { ローカル変数 [':' タイプ] } ')' ]
[':'
戻り値タイプ]
( '{' 文 '}' | ';' ) ;
宣言要素を省略した場合の意味は以下のとおり。
関数定義 = 'function' 名前 '(' {
仮引数 } { ローカル変数 } ')'
'{' 文 '}' (* AWK標準スタイル *)
| 'function' 名前 '(' { 仮引数 } ')' '(' { ローカル変数 } ')' '{' 文 '}' (* ローカル変数を()で明示的に宣言 *)
| 'function'
名前
'{' 文 '}' (* 仮引数とローカル変数宣言なし *)
| 'function' 名前 ['(' { 仮引数 } ')'] ';' (*
関数プロトタイプ宣言 *)
| 'function'
'{' 文 '}' (* 無名関数 *)
;
関数(メソド)呼び出しは以下のとおり。
関数呼び出し = 名前 ['(' Expression
{ ',' Expression } ')']
;
Note:
関数呼び出しパラメータが空の場合の '()' は省略可能であり 関数呼び出しとプロパティ参照の区別はない。
Note:
パラメータを区切る ',' は ')(' で置き換え可能であり 関数型言語でのカリー化 (Currying) 記述が可能、
さらに '(' ')' は '{' '}'に置き換え可能。
fun(a, b); fun(a)(b)
# AWK仕様で'('の前に空白は記述不可
(* 文字列結合と競合 *)
fun(a) {b}
# 独自構文に似せた呼び出しが可能
関数値は他の関数と同じように呼び出せる関数オブジェクトで、
apply メソドが呼び出されたときに実行される。
関数値 = '.' 関数呼び出し ;
function add(a, b) { return a
+ b }
function calc(x: Function)
{ return x.apply
} # 関数値呼び出し
print calc(.add(1, 2))
# 3
組み込み変数は以下のとおりで GNU AWKの主要な拡張機能をサポートする。
- ARGC
- ARGV の要素数
- ARGIND
- 配列 ARGV のインデックス (現在処理中のファイル名が格納されている要素を指す)
- ARGV
- コマンド行引数配列 (添字 1 より格納され AWK へのオプションは含まない)
- ARGV[0] の内容は不定。
AWK(C言語インターフェイス) では実行プログラム名が格納されるが Java にはその概念はない
- BINMODE
- 入出力においてバイナリモード
を制御 (Cygwin
における行末の改行 "\n", "\r\n" 対策に相当)
- CONVFMT
- 数値から文字列への変換書式 (既定値は %.6g)
- ENVIRON
- 起動時の環境変数のコピー配列
- ERRNO
- 入出力例外の理由を表わす文字
列
- FIELDWIDTHS
- 固定長レコードを入力するため
の空白で区切られたフィールド長のリスト (ASCII コード依存)
- FILENAME
- 現在の入力ファイル名
- FNR
- 現在の入力ファイルから入力したレコード数
- FS
- 入力フィールドセパレータで 正規表現文字列 を受け付ける (既定値は空白で 空白 と TAB
にマッチする)
- IGNORECASE
- 文字列比較と正規表現マッチングで英大小文字を区別 (既定値は 0 て英大小文字を区別する)
- LINT
- コマンドラインオプション
"--lint"
の有無をアプリで制御
- NF
- 現在の入力レコードのフィールド数
- NR
- 現在までに入力したレコード数の合計
- OFMT
- 数値の出力書式 (既定値は %.6g)
- OFS
- 出力フィールドセパレータ (既定値は空白)
- ORS
- 出力レコードセパレータ (既定値はプラットフォーム
依存の改行 "\n", "\r" または "\r\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 [ #文字コードセット
]"
- ユニフォームリソースロケータ (Uniform Resource Locator) つまり World Wide
Web 上のリソースへのポインタを表す
- "file:// URL [
#文字コードセット
]"
- ローカルファイルを表す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 で置換し置換数を返す
置換文字列 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)
- 小文字をすべて大文字に変換した文字列を返す
ビット操作関数は以下のとおり。 (精
度は unsigned int 32bit)
- and(x, y)
- x AND y を返す
- or(x, y)
- x OR y を返す
- xor(x, y)
- x XOR y を返す
- compl(x)
- x の2の補数を返す
- lshift(x, count)
- x を count ビット左にシフトした値を返す
- rshift(x, count)
- x を count ビット右に0を充填してシフトした値を返す
時間関数は以下のとおり。
- systime()
- 基準時点 (1970-01-01 00:00:00 UTC,) からの経過秒数(タイムスタンプ)を返す
- mktime(datespec)
- 日付時刻を表す文字列をタイムスタンプに変換して返す
- java.text.DateFormat を実装。
引数は "2007/02/28 00:00:00" など
- strftime([ format [ , timestamp ] ])
- 指定したタイムスタンプ (省略時は現在時刻) を日付時刻を表す文字列に変換して返す
java.text.SimpleDateFormat
を実装。 format省略時は Java デフォルトスタイル
プラットフォーム非依存とするために以下の (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 *) |
照合 |
= 式
'~' 正規表現 (* 適合 *)
| 式
'!~' 正規表現 (* 非適合 *)
; |
関係 |
= '<' | '<=' | '>' | '>=' | '!=' | '=='
| '!==' | '===' (* 参照等価 *)
; |
連接 |
(* 文字列の結合、空の演算子
*) |
和、差 |
= '+' | '-' ; |
積、商、剰余 |
= '*' | '/' | '%' ; |
単項和と差 |
= '+' | '-' ; |
論理否定 |
= '!' ; |
累乗 |
= '^' | '**' ; |
インクリメント、デクリメント |
= '++' | '--' ; |
関数値 |
= '.' 関数呼び出し
; |
欄 |
= '$' ; |
グループ化 |
= '(' 式 ')' ; |
AWK 正規表現エスケープシーケンスとの非互換点について説明する。
- \\
- バックスラッシュ文字
- \a
- アラート文字 (BEL)
正規表現 /\a/ は有効、 文字列エスケープ "\a"
は不可 ("\u0007"
で指定する)
- \b
- 単語境界を表すメタ文字で '['
文字クラス ']' でのみ
後退文字(BS)としての意味を持つ
- \cx
- x に対応する制御文字
- \e
- エスケープ文字 (ESC)
- \f
- 用紙送り文字 (FF)
- \n
- 改行文字 (LF)
- \r
- 復帰文字 (CR)
- \t
- タブ文字 (TAB)
- \v
- 垂直タブ (VT)
エスケープ指定は不可 ("\u000B"で指定する)
- \0nnn
- (\1 ~ \9
は前方参照指定で使用するため)
0 で始まる 8
進値を
1 から 3 桁で指定する
- \xhh
- 2 桁 (n 桁 \xhh… 指定は不可) の
16 進値
- \uhhhh
- 16 進値 0xhhhh を持つ
Unicode エスケープ
- \/
- スラッシュ文字 (/正規表現/ で使用する)
- \"
- 二重引用符文字 ("正規表現文字列" で使用する)
非同期計算スレッド (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 |
ブール型 |
Number |
数値型の総称 |
Int |
短整数型の総称 (int, Integer) |
Double |
実数または長整数型の総称 (Double, Float, Long) |
String |
文字列型の総称 (String, CharSequence) |
AryMap |
連想配列 |
Function |
関数値 |
Reference |
参照変数 |
AnyRef |
コンパイラに型推論を依頼する、推論できない場合は Object |