D_fmt - Dコマンドのフィールドフォーマットリスト

[ 英語 | 日本語 ]

[Dホームページへ]

説明

Dフォーマットは文字列とDフィールドの相互変換を 指定する仕様である。 DフォーマットはDコマンドのフィールドリスト (Dintro参照) の付加情報として指定される。 文字列からDフィールドへの変換仕様を「入力」フォーマットと呼び,最も普通には DfromLine, で使用するが, Duntie および Dunpack でも使用する。 Dフィールドから文字列への変換仕様を「出力」フォーマットと呼び,最も普通には DtoLine で使用するが, Dtie および Dpack でも使用する。 出力フォーマットは,一部 Dpr でも使用する。 入力および出力フォーマットは同じ構文を持つが, 意味するところは若干異なる。

入力または出力フォーマットの変換動作においては 文字列側にカレントポジションを仮定する。 カレントポジションは,文字列上でポジションの前にある文字の数で表す。 0ではじまる文字位置で指定すると言ってもよい。 Dフォーマットは文字のエンコーディングについて関知しないし, C-formatを除けば, バイトやオクテットという概念もない。

構文

field-format-list ::= field-list of field-name[:format].
format ::= [start] [end] [options] [repeat] [:C-format]
start ::= absolute | relative
  absolute ::= DIGITS
  relative ::= +DIGITS
end ::= end-position | length | delimiter | pattern
  end-position ::= -DIGITS
  length ::= (DIGITS)
  delimiter ::= /STRING/
  pattern ::= @STRING@
options ::= { alignment | quoting | with-field-name }..
  alignment ::= l | r | n
  quoting ::= q | x | Q | b | n
  with-field-name ::= f | n
repeat ::= *
C-format ::= scanfまたはprintfのフォーマットで 一つだけ%をもつもの

ここでDIGITSは"0"から"9"までの文字の列, STRINGは任意の文字の列である。 (なお, フォーマットと特殊文字の節を参照)。

コマンドオプションとフィールドフォーマットリスト

フィールドフォーマットリストを使用するコマンドには, -t および -z の2つのコマンドオプションが使用できる。 これらのオプションは end および options の省略時値を規定する。

-t STRING
省略時の delimiterとなる STRINGを与える。 ただし前後を囲むSOLIDUS (/)は -tオプションでは使用しない。 STRINGは省略してはならない。 NULL文字列を指定したい場合 -t "" と指定すること。 -t が指定されない場合, 省略時区切り字は制御文字TABとなる。
-z options
省略時の options を与える。 このオプションは, options を指定されていないフィールドエントリ および省略時フォーマットに有効となる。 一つでも options が指定されているフィールドエントリについては たとえカテゴリ (alignmentquotingwith-field-name) が異なっていても -z オプションは適用されない。

1つのDコマンドに2つのフィールドフォーマットリスト が指定される場合がある。 この場合, -t および -z オプションは,双方のフィールドフォーマットリストに対して 適用される。

入力フォーマット

動作

入力フォーマット動作は,フィールドフォーマットリストの 最初のフィールドエントリで,カレントポジション (cp)の値を0にセットして開始する。

入力スキャナーは cp を現在のフィールドエントリの start の位置にセットし, end の位置までの文字を読み込む。 フィールドエントリに optionsが指定されている場合, 読み込みはそのオプションによってコントロールされる。 読み込み後,もしあれば C-format による変換を行ってDフィールドを作成する。 Dフィールドの作成後,, cpend の仕様で決められている位置に移動する。

repeat 指定がある場合,この新しい cp から,同じフィールドエントリについての処理を繰り返す。 これは, cp が入力文字列の終わりに達するまで繰り返される。

1フィールドエントリの処理が終わると, 入力スキャナはフィールドフォーマットリストの次のフィールドエントリに移動する。 (これはたとえ cp が入力文字列の後端に達していても終わらない)。 フィールド名がNULL文字列の場合, フィールドはスキップされる。 (フィールドの読み込み動作は行われるが, Dフィールドの作成は行わない)。 以上の処理が,フィールドフォーマットが終わるまで 繰り返される。

スタート

DIGITS
absolute; この値がスタート位置となる。
+DIGITS
relative; この値を cp に足したものがスタート位置となる。

start の省略時は, cp となる。

エンド

-DIGITS
end-position; DIGITSの値までをフィールドとして読み込む。 新しい cp は,この値の次の位置に移る。
(DIGITS)
length; この値の文字数を読み込む。 新しい cp は次の位置に移る。
/STRING/
delimiter; STRINGの正規表現を区切り字として start 位置からスキャンし, マッチした位置の前までを読み込む。 マッチしない場合またはSTRINGがNULL文字列 (//)の場合,入力文字列の終わりまで読み込む。 新しい cp はマッチした区切り字文字列の次の位置に移る。
@STRING@
pattern; patternを正規表現として start 位置からマッチする。 通常, patternは正規表現"^"ではじめ, cp からのマッチに限定するが, 必ず"^"で始めなければならないわけではない。 patternにマッチする限りの部分がフィールドとして読み込まれる。 patternが最初からマッチしない場合, 読み込みは行われず 対応するDフィールドも作成されない。 (NULL文字列を値とするDフィールドを作成するわけではないことに注意)。 新しい cp は,マッチした文字列の次の位置に進む。 マッチしない場合, cp は次の文字に移動する。

endの省略時動作は -t で指定された区切り字であるが, -t のない場合, /TAB/ (制御文字tab)が使われる。

オプション

整列オプション

整列オプションは固定長入力( end-position または length 指定) の場合に使用され, 先行または後続空白文字を除去する。 可変長入力( delimiter または pattern 指定)の場合,無効である。

l
左整列; 後続の空白文字を除去する。
r
右整列; 先行空白文字を除去する。

lr との双方が指定されている場合, 先行空白と後続空白の両方を除去する。

クォーティングオプション

クォーティングオプションは可変長入力 (delimiter または pattern指定)に使用し, 区切り字をエスケープするために用いられる。 固定長入力に指定しても無効である。

q
""クォーティング; delimiter のスキャン中QUOTATION MARK (") が現れると,対応するQUOTATION MARKまでの 間の文字列は区切り字とならない。 また,これを囲むQUOTATION MARKは除去される。 pattern のマッチング中にQUOTATION MARK が現れる(このQUOTATION MARKが patternにマッチする必要がある)と, 対応するQUOTATION MARKまでの文字列は, patternにマッチするか否かにかかわらず 読み込まれてフィールドの一部となる。 囲んでいるQUOTATION MARKは除去される。 このクォーティング中,QUOTATION MARKの連続("") は,1文字のQUOTATION MARKとして読み込まれ, クォーティングの終了とはならない。 ただし,xオプションが指定されているときは, この限りでない。 次項参照。
x
UNIXモードクォーテーションエスケープ; qオプションとともに使用する。 このオプションは,QUOTATION MARKでクォーティング するとき,中でQUOTATION MARKを使用するための方法を変更する。 このための方法には,2つの伝統がある。 csv(およびIBMメインフレーム系のソフトの多く)では "abc""def"abc"defとなる。 この方法が,Dフォーマットでも標準である。 しかしUNIX系の多くのソフトでは"abc\"def"を使用する。 このxオプションは,UNIX系の方式に切り替える。 また,連続したREVERSE SOLIDUS(\\)は1文字のREVERSE SOLIDUSになる。
Q
''クォーティング; qクォーティングと同じであるが,クォーティングするための 文字がQUOTATION MARKでなく,APOSTROPH(')となる。 APOSTROPH自体をクォーティングする方法はない。 もし,APOSTROPHをDフィールド中で使用したい場合,他のクォーティング 方法を使うこと。
b
\クォーティング; delimiter のスキャン中REVERSE SOLIDUS (\) が現れると,そのREVERSE SOLIDUSは消去され, 次の文字は区切り字(またはその一部)にはならない。 pattern マッチング中にREVERSE SOLIDUS がマッチすると,そのREVERSE SOLIDUSは除去され, 次の文字がなんであれフィールドとしての読み込み対象となる。

qQbが同時に指定された場合, 最初に現れたものが閉じるまで,他のものは無効となる。 すなわち,QUOTATION MARK (")の中では, APOSTROPH (')やREVERSE SOLIDUS (\)は通常の文字であり, APOSTROPH (')のなかでは, QUOTATION MARK (")やREVERSE SOLIDUS (\)が通常の文字となる。 REVERSE SOLIDUS (\)は上記のクォーティング開始文字を通常の文字に する。オプションxは,オプションqに従属してQUOTATION MARK の中だけに有効なものであり,上記のルールに関係しない。

フィールド名付オプション

フィールド名付オプションは,ややトリッキーな機能である。

f
入力文字列は値だけでなく,フィールド名もついた文字列とする。 読み込まれた文字列が全体として1つのDフィールドとなる。 したがって,入力文字列はfield-name:value という形をしていなければならない。

fオプションを使う場合, フィールド名は入力文字列からとられるので, フィールドフォーマットリストに書かれるフィールド名は意味を持たない。 フィールドフォーマットに書かれるフィールド名は単に無視されるので, 何を書いてもかまわない。 ただし,このような場合"."を書いておくことが推奨される。

現在の実装では,fオプションで読み込まれる文字列に 本当にCOLONがあるかどうかのチェックは行なっていない。 正しい文字列を用意するのはユーザ側の責任で行うこと。

キャンセルオプション

オプション n は,カテゴリに関係なく他のオプションを無効にする。 これは, -z オプションで有効になる省略時オプションを,個別のフィールドエントリで 無効にしたい場合に使用する。 たとえば,4つのフィールド"a","b","c","d" が入力行中でTABで区切られているとする。 このうちフィールド"b","c","d"を -q オプション付きで読み,フィールド"a"をオプションなしで読む指定を

-z q "a:n,b,c,d"

のように書ける。これは,次のように指定したのと同じである。

"a,b:q,c:q,d:q"

リピート

*
フィールドは cp が入力文字列の終端に達するまで, 読み込みを繰り返す。

start指定が absolute または end-position のフィールドエントリに repeat は指定できない。

Cフォーマット

C-format が指定されたとき, 読み込まれた文字列は C言語の関数sscanf でさらに変換されて,最終結果となる。 読み込まれた文字列は, 指定の C-format をフォーマットとし, 読み込まれた文字列を 入力文字列として, sscanf に渡され,スキャンされた結果が 再度文字列に変換されて最終結果となる。

C-formatは, ただ1つだけ有効なフォーマット指定子を持たなければならない。 フォーマット指定子は,PERCENT SIGN (%)で 始まって,次の形式であること。

%[*][width][size]type

マーク*をもつフォーマット指定子は,有効なものとしては数えない。 また,%%は,1文字のPERCENT SIGNにマッチするが, これも有効なものとしては数えない。

C-formattypeは,次のいずれかであること。

'd', 'i', 'o', 'u', 'x', 'X', 'f', 'e', 'E', 'g', 'G', 's', 'S', 'c', 'C'

sizeを指定するときは,次のいずれかであること。

'h', 'hh', 'l', 'll', 'L', 'w', 'I64'

Widthは,10進整数で,変換に使用する最大文字数を指定する。 C-formatでは, type'c'または'C' のときのwidthは,指定しない,あるいは1を指定すること。 空白にかかわらず,複数文字数読み込みたい場合には, Dフォーマットの エンド指定lengthを使えばよい。

type's'または'S'のとき, 変換結果は文字列変数に格納され,これが最終結果となる。 その他のすべてのtypeのとき, 変換結果は適切な型の変数に格納され,さらに数値に変換される。 現在のDコマンドの実装で,数値はdouble型で表されるので, 格納した変数から数値への変換は,C言語のdouble型への変換規則に従う。 最終的には,Dコマンドの 数値 表現規則により文字列となる。

type 'c' も,上記の規則に従う。 入力文字列の1文字(バイト)が, char型変数に格納されてから,double型に変換される。 したがって,結果の値はその文字の内部コード値である。 type 'c'size 'l'または'w'が指定されている あるいは,type'C'のときは, 1マルチバイト文字が,その内部コードに変換される。 このC-formattype 'c'は, Dコマンドが例外として,文字コードを扱う唯一のケースである。

なお,C-format を指定した場合,オプション f を同じフォーマットエントリ中に使用することはできない。

このDコマンドのC-format仕様は, 実行環境のライブラリ関数と一致するとは限らない。 たとえば, size 'I64'は, Windowsでは受け入れられるが,ほかの実行環境ではエラーとなる。 標準Cではtype 'n'があるが, このDコマンドのC-formatでは許されない。 C-format変換が正常に行われるには, Dコマンドと実行環境のsscanfのフォーマット仕様の 共通部分だけを使用することが必要である。

C-formatで非ASCII文字を扱う場合注意しなければならない点がある。 Sscanf関数は, ロケールの文字コードで実行される。 UTF入出力機能を使用している場合, いくつかの文字はロケールの文字コードでは表現できないことがある。 この場合,その文字はsscanfの実行前に取り除かれる。 マルチバイト文字とロケール文字コードに関しては, C-formatの使用法によってはエラーコードを生成する可能性がある。 たとえば,C-format "%1s"は, マルチバイト文字の一部だけを取り出すことがある。 このような場合,エラーコードとなったものは,最終的な文字列値から取り除かれる。 これらの問題は,ASCII文字だけ使用している場合には,おこらない。

省略時フィールドエントリ

フィールドエントリにフォーマット付加情報がない場合, 省略時フィールドエントリが適用される。 (もっとも,これが大多数の場合であろう)。 上記の節に記した省略時の値が省略時フィールドエントリの値となる。 すなわち,cpstartの値とし,-tコマンドオプションの値 (あるいは-tがなければTAB)をdelimiterの値とし, -zコマンドオプションの値をoptionsの値とし, あるいは-zがなければoptionsは指定なし, そしてrepeatおよびC-formatに何も指定がないものである。

ハードデリミタとソフトデリミタ

cp が入力文字列の終端にある場合, start指定 が absolute で戻されない限り, フィールドは読み込まれない。 しかし,これに例外がある。 次の例のように区切り字がCOMMAで,入力文字列が COMMAで始まり,COMMAで終わっているとき:

DfromLine -t "," "a,b,c"
,word,

自然な結果は次のようなものであろう。

a:
b:word
c:

しかしながら,区切り字が1文字以上の空白であった場合で, 入力文字列がCOMMAの代わりに空白で始まり,空白で終わっているとき:

-t " +" "a,b,c"
 word 

この場合,

a:word

という結果が自然と思われる。

この現象を一般化するために ハードデリミタとソフトデリミタという概念を導入する。

ある区切り字パターンに対して ある文字列がこの区切り字パターンにマッチするが この文字列を2つ重ねた文字列はマッチしないとき, この文字列はこのパターンに対して「ハード」であると定義する。 2つ重ねた文字列も,同じパターンにマッチする場合, 「ソフト」であると定義する。

例を示すと,文字列","は区切り字パターン/,/にマッチする。 しかし,",,"はマッチしない。したがって,","は/,/ に対して「ハード」である。 これに対し空白1個も,空白2個も,区切り字パターン/ +/にマッチする。 したがって空白1個は,/ +/に対して「ソフト」である。

cp が入力文字列の終端にあって,その前の区切り字 (区切り字パターンにマッチした文字列)が「ハード」だった場合, 対応するフィールドエントリはNULL文字列として読み込まれる。 さらに, cpからはじまる「ソフト」な区切り字は,読み込み前にスキップされる。 (cpから「ハード」な区切り字があった場合,NULL文字列が読み込まれる。) これらの規則は,当然であるが, delimiter指定のフィールドエントリだけに適用される。 固定長フィールドエントリやpattern指定のフィールドエントリには関係しない。

例をあげる:

DfromLine -t " *, *| +" a,b,c,d,e
  A B , ,D  ,

デリミタは,前後に1つ以上のSPACEがついてもよいCOMMA, または1つ以上のSPACEである。 結果は,次のようになる。

a:A
b:B
c:
d:D
e:

指定のデリミタに対し, 入力行の先頭にある"SPACE SPACE" は,ソフトであるが, "B"の後ろにある"SPACE COMMA SPACE"および行の最後にある"SPACE COMMA"は,ハードであるため,このような結果になる。

入力文字列が空文字列の場合, cp は最初から終端にいて,前の区切り字が「ソフト」か「ハード」かは 決められない。 この場合,最初のフィールドの区切り字が空列の (したがって入力文字列全体を読み込む)場合, 「ハード」を仮定し,そうでなければ「ソフト」を仮定する。 言い換えれば,空文字列を入力しても 通常ではフィールドはひとつも読み込まれない。 ただし,-t ""://の指定によって 入力文字列全体を読み込もうとするときに限り, 値が空文字列の1フィールドが読み込まれる。

このような「ハード」,「ソフト」の定義は 数学的な精密さには欠ける。 実際,パターン",,?,?"に対し ","はソフトだが",,"はハードになるという ような奇妙な現象もおこる。 より良い「ハード」「ソフト」の定義があるかもしれない。 しかし,現在の定義は通常のケースに対し十分と思われる。 開発コストを考えると当面この定義を改良する予定はない。 (もっとも,空白列はソフトでそのほかはハードといった 単純な定義でも良いかもしれないが…)

出力フォーマット

動作

出力動作には2つのタイプがある。 1つはDレコード順出力で,これが標準である。 もう1つはフィールドフォーマットリスト順出力で, たとえばDtoLine-pオプションが指定されたときに行われる。 この2つのちがいは,フィールドの出力順だけである。

Dレコード順出力では,Dレコードの最初のDフィールドをカレントフィールドとしてはじまる。 ただし,Dtieの場合はDレコードのフィールドの部分集合の最初のDフィールドからはじまる。 cpはゼロにセットされる。 出力ルーチンはフィールドフォーマットリストのカレントフィールドと同じフィールド名の エントリをさがし, もしあれば,それをカレントフィールドエントリとして以下の出力を行う。 見つからなかった場合,省略時フィールドエントリによって出力を行う。 1フィールドの出力が終わると,Dレコードの(またはDtieの場合そのサブセットの) 次のフィールドがカレントフィールドになる。 以下同様に,Dレコードまたはそのサブセットの全Dフィールドを処理するまで続く。

フィールドフォーマット順出力では,最初にフィールドフォーマットリストの 最初のフィールドエントリをカレントフィールドエントリとする。 cpはゼロにセットする。 出力ルーチンは,Dレコードの中にその名前のフィールドがあるかどうかを探す。 見つかった場合,そのDフィールドをカレントフィールドとして出力動作が行われる。 2つ以上のDフィールドが見つかった場合,2番目のフィールドをカレントフィールドとして, 出力動作が行われる。 見つかったフィールドがすべて出力されるか, 最初から同名のフィールドが見つからなかった場合, フィールドフォーマットリストの次のエントリにカレントフィールドリストが移動する。 この動作が,フィールドフォーマットリストの全エントリが処理されるまで続く。

カレントフィールドとカレントフィールドエントリが決まると,(もしあれば) C-formatによる変換を行い, 次いでstart指定によるcpの調整, endによって出力する字数の調整またはdelimiterの付加を行なって出力する。 出力後 cp は出力した文字列の終端にある。

出力ルーチンレベルでの「バッファリング」は行わない。 一旦フィールドが出力されると, cp は戻ることがない。 フィールド"b"を1-4カラムに, フィールド"a"を6-9カラムに出力したいなら, フィールド"b"はフィールド"a"の前に処理されるように 指定しなければならない。

スタート

DIGITS
absolute; この値がスタート位置となる。 cp が,この値より小さいとき,SPACEで埋められる。 cp がこの値より大きいとき,警告メッセージをプリントして, スタート位置は cp からとなる。
+DIGITS
relative; この値を cp に足したものがスタート位置となる。 出力前にSPACEが挿入される。

省略時の startcp からである。

エンド

-DIGITS
end-position; フィールドはこの値の場所で終わる。 整列オプションに従って 出力を切り捨てるか,SPACEを埋めるかして 調整する。 出力開始位置が end-position より大きい場合, 警告メッセージをプリントし,カレントフィールドの 出力は行わない。 cpend 位置プラス1の位置に移動する。
(DIGITS)
length; 出力長をこの値にする。 整列オプションによって切り捨てまたはSPACEの埋め込みが行われる。 cp はスタート位置プラス length の位置に移動する。
/STRING/
delimiter; STRINGを出力データの後ろに付加する。 ただし,カレントフィールドが出力すべき最後のフィールドの場合 この付加は行なわれない。 cp はスタート位置プラス出力フィールド長プラスSTRING長(最後でないとき) に移動する。

出力フォーマットに pattern 指定は存在しない。

オプション

整列オプション

整列オプションは固定長入力( end-position または length 指定) の場合に使用され, 出力長の方が短い場合SPACEを埋め, 出力長の方が長い場合切り捨てを行う。 可変長入力( delimiter または pattern 指定)の場合,整列オプションは無効である。

l
左整列; 値の後ろにSPACEを埋める,または値の終端から切り捨てが行われる。
r
右整列; 値の前にSPACEを埋める,または値の先頭から切り捨てが行われる。

出力フォーマットにおける整列オプションは互いに排他である。 ただし, lr との双方が指定された場合, l が優先される。

クォーティングオプション

クォーティングオプションは可変長入力 (delimiter指定)に使用し, 区切り字をエスケープするために用いられる。 固定長入力に指定しても無効である。

q
""クォーティング; 値全体をQUOTATION MARK (")で囲って出力する。 値にQUOTATION MARKがあった場合, xオプションの有無によって REVERSE SOLIDUSを前につけるか 2文字のQUOTATION MARKに変換される。
x
UNIXモードクォーテーションエスケープ; qオプションとともに使用する。 省略時,""に囲まれた値の中のQUOTATION MARKは二重化される。 しかし,このオプションが指定されると,QUOTATION MARKは, REVERSE SOLIDUSとQUOTATION MARK (")に変換される。 さらに,QUOTATION MARKまたはREVERSE SOLIDUSの直前にある REVERSE SOLIDUSは二重化される。
Q
'' quoting; qクォーティングと同じであるが,クォーティングするための文字がQUOTATION MARKでなく,APOSTROPH(')となる。 値の中のAPOSTROPHはそのまま残るので,APOSTROPHのあるデータにこのオプションを 使うべきではない。
b
\ quoting; delimiter の最初の文字が値の中に現れたとき, その文字の前にREVERSE SOLIDUS(\)を付加する。 値中のREVERSE SOLIDUSは二重化される。(\\)。

出力フォーマットのクォーティングオプションは互いに排他である。 ただし,これらが同時に指定された場合, qが優先し,次にQが優先する。

フィールド名付オプション

f
値のまえにフィールド名とCOLONをつけて出力される。

キャンセルオプション

n オプションは他のオプションをキャンセルする。 これは -z コマンドオプションが使われている場合, フィールドフォーマットリストのエントリで, それをキャンセルするために用いる。

リピート

出力フォーマットにおけるリピートは無視される。 フィールドがリピートするかどうかは,出力対象の Dレコードにフィールドが複数あるかどうかに支配され フィールドフォーマットリストに支配されるわけではない。 ただし,フォーマットがリーフフィールドリストとして 使用されるときのみリピートに意味がある。 D_lsa のマニュアルを参照。

Cフォーマット

C-formatが指定されたとき, フィールド値は出力前に,C言語の関数sprintfで変換される。 変換は,C-formatをフォーマットとし, フィールド値を引数としておこなわれ, 変換結果の文字列値が,通常のDフォーマットの処理に引き渡される。

C-formatは,ただ1つだけフォーマット指定子をもつこと。 フォーマット指定子は,PERCENT SIGN (%)ではじまって, 次の形式であること。

%[flags][width][.precision][size]type

2文字連続の"%%"は,1文字のPERCENT SIGNをあらわす。 これは,フォーマット指定子しては数えない。

flagsは,次の文字の組み合わせであること。

'#', '0', '-', ' ', '+'

これらのフラグは,右詰左詰,符号の表示法,16進プリフィクス など,表示方法を変更する。 詳細は,C言語のsprintfを参照。

typeは,次のいずれかであること。

'd', 'i', 'o', 'u', 'x', 'X', 'f', 'e', 'E', 'g', 'G', 's', 'S', 'c', 'C'

sizeを指定するときは,次のいずれかであること。

'h', 'hh', 'l', 'll', 'L', 'w', 'I64'

widthprecisionは十進整数で, typeに応じて結果の文字列のある種の文字数を制御する。 詳細は,C言語のsprintfを参照。 ただし,widthprecisionでは, 数値変換の場合,結果の文字列の長さの上限は指定できない。 これは,sprintfの仕様によるものである。 長さの上限を指定するには,Dフォーマットの エンド指定lengthを使えばよい。

typeが数値 ('s'または'S'以外)の場合, もとのフィールド値は一旦数値(現実装ではdouble型)に変換され, さらに,typesizeとで指定された型に変換されて から,sprintf関数に渡される。 sprintfで処理された後,変換された文字列は内部文字列値 (現実装ではwchar文字列)に正規化されてから,Dフォーマットの 処理に入る。

type 'c'または'C'も数値である。 この場合の,sprintf変換は,内部コードから1文字への変換となる。 size'l'であれば, マルチバイト文字も扱うことができるが, そうでなければ,1バイトの範囲に限られる。

type's'または'S'のとき, sprintf関数は,値を変換しない。 C-format "%s"は,基本的に何も変換しないのと同じである。 これらは,通常元の文字列に文字を付加するために使われる。 たとえば,"(%s)"は,元の文字列を括弧ではさむ。 type 's'で, size 'l'を使用してもよい。 ただし,widthおよびprecisionの数え方 が変わるのをのぞけば,結果は同じである。 なお,widthおよびprecisiontype 's''S'で使用することは, 推奨しない。

なお,C-format を指定した場合,オプション f を同じフォーマットエントリ中に使用することはできない。

このDコマンドのC-format仕様は, 実行環境のライブラリ関数と一致するとは限らない。 たとえば,size 'w'は, DコマンドのC-format指定としては正しいが, Windowsではエラーとなる。 標準Cでは,type 'p'があるが, DコマンドのC-formatとしては,許されていない。 C-format変換が正常に行われるには, Dコマンドと実行環境のsprintfのフォーマット仕様の 共通部分だけを使用することが必要である。

C-formatで非ASCII文字を扱う場合注意しなければならない点がある。 Sprintf関数は,ロケールの文字コードで実行される。 UTF入出力機能を使用している場合, いくつかの文字はロケールの文字コードでは表現できないことがある。 "%lc"フォーマット指定でそのような文字を変換した場合の結果は, 実行環境に依存する。 また,C-format "%s"では, sizeprecisionはバイト単位でカウントされる。 このため,正しくない文字コード表現を生じる可能性があるが, このような場合の結果も,実行環境依存である。 これらの問題は,ASCII文字だけ使用している場合には,おこらない。

省略時フィールドエントリ

フィールドフォーマットリストにフォーマット付加情報のないとき, または,フィールドエントリが見つからないとき, 省略時フィールドエントリが使われる。 これは上記の述べた省略時の値をあつめたエントリで, cpstartの値とし, -tコマンドオプション(-tがなければTAB) をdelimiterとし, -zコマンドオプションをoptionsの値とし, -zがなければoptionsはなし, そして,C-formatは何も指定のないものである。

フォーマットと特殊文字

フィールドフォーマットリストの中では, REVERSE SOLIDUS (\), DOLLAR SIGN ($) やAMPERSAND (&) のような特殊文字を使うことが多い。 得に入力フォーマットでは必要性が大きい。 Dフォーマットの処理に正しく文字列を渡すには, shellや,Dフィールドリストでの特殊文字を 正しくエスケープしなければならない。 次に示すのは,そのための実用的指針である。

  1. Unix shellでは,APOSTOROPHE (')で囲む。 Windowsのcmd shellでは,QUOTATION MARK (")で囲む。
  2. REVERSE SOLIDUSは2重化する(\\)。
  3. フィールドの区切りでないCOMMは,REVERSE SOLIDUSを前につける(\,)。
  4. /STRING/の中では,SOLIDUSの前にREVERSE SOLIDUSをつける(\/)。
  5. @STRING@の中では,COMMERCIAL ATの前にREVERSE SOLIDUSをつける(\@) 。

多くの場合,上記の指針ですむが, shellやDコマンドが,コマンド引数をどのように処理するかの詳細を 知っていた方が,誤りなく指定するのに役立つ。 処理にはshell (WIndowsではcmd shell)とDコマンドの2つのレベルがある。 Dコマンド中の処理はさらにDフィールドリストの解析処理, 次にDフォーマットの解析処理, delimiterまたはpatternに対しては, 正規表現のマッチング処理などのレベルがある。 各レベルにおいて,エスケープ文字が除去される。 以下にその詳細を示す。

UNIX shellでは空白文字は,前にREVERSE SOLIDUS (\)をつける, またはQUOTATION MARK (")もしくはAPOSTROPH (')で囲む ことによって引数に含めることができる。。 そのほかの特殊文字,例えば, GREATER-THAN SIGN (>), DOLLAR SIGN ($)や AMPERSAND (&)も同様のエスケープが可能である。 エスケープの方法は,sh(1)とcsh(1)で 若干の差はあるが,ここでは詳細は略す。 通常,フィールドフォーマとリストは,APOSTROPHで囲むのが安全であり, どのshellでも通用する。 フォーマット中でAPOSTROPHを使う場合,それをQUOTATION MARKで囲む。 1つの引数に複数の引用符対を使ってもかまわない。 引数'"DON'"'"'NT"'は,コマンドに渡されるときには 7文字の文字列"DON'T"となる。

Windowsのcmd shellでは空白文字は,QUOTATION MARKで囲むことにより 引数に含めることができる。 そのほかの特殊文字,例えば, GREATER-THAN SIGN (>), DOLLAR SIGN ($)や AMPERSAND (&)も QUOTATION MARKでエスケープできる。 また,CIRCUMFLEX ACCENT (^)を前につけることによっても エスケープできる。 QUOTATION MARKを引数に含めるには, QUOTATION MARK内でQUOTATION MARKを2個連続させる("")。 CIRCUMFLEX ACCENTをコマンド引数に含めるには, QUOTATION MARK内にいれるか,CURCUMFLEX ACCENTを2個連続させ得る。 これらの特殊文字の他に,PERCENT SIGN (%) も,環境変数と解釈される場合にはエスケープしなければならない。 例えば,%path%は,cmd shellによってpathディレクトリリスト に置き換えられる。 ほとんどの場合,環境変数との衝突を心配する必要はないが, もし,%xx%のような文字列をフォーマット中で使う場合, 2番目の%の前にCIRCUMFLEX ACCENTをつけることにより エスケープできる。(xのまえにつけてもよい)。 環境変数は,QUOTATION MARKによってエスケープすることはできない。

これらshellのエスケープ文字は,引数がDコマンドに渡されるときには, 除去される。

shellの処理に続いて,Dコマンドが引数を受け取る。 Dフィールドリスト解析処理 が次の処理を行う。

  1. フィールドリストの先頭がCIRCUMFLEX ACCENT (^)であればそれを取り除く (排他フィールドリスト)。
  2. フィールドリストの先頭がREVERSE SOLIDUSとCIRCUMFLEX ACCENTであれば, 先頭のREVERSE SOLIDUSを取り除く。
  3. 各<field name>の中で COMMAまたはREVERSE SOLIDUSの直前にあるREVERSE SOLIDUSを取り除く。
  4. 各<additional-inf>の中で, COMMAの前にあるREVERSE SOLIDUSを取り除く。 REVERSE SOLIDUSの直前にあるREVERSE SOLIDUSは以降の解析処理のために保持される。

<additional-inf>がDフォーマット解析処理に欠けられる。 この処理では:

  1. delimiter (/STRING/)中の REVERSE SOLIDUSでSOLIDUS (/)またはREVERSE SOLIDUSの直前にあるものは取り除く。
  2. pattern (@STRING@)中の REVERSE SOLIDUSでCOMMERCIAL AT (@)またはREVERSE SOLIDUSの直前にあるものは取り除く。
  3. C-format中の REVERSE SOLIDUSでREVERSE SOLIDUSの直前にあるものは取り除く。

結果の文字列が,正規表現マッチングなどのDフォーマットのフォーマッティング 処理に引き渡される。

特殊文字の使用例

フィールドfooのフォーマットのdelimiterとして SOLIDUS (/), VERTICAL LINE (|)または REVERSE SOLIDUS (\) いずれか1文字という区切り字を使用したいとする。

正規表現は次のようになる。

/|\||\\

最初のSOLIDUSは,通常文字。 次のVERTICAL LINEは,ORの意味の正規表現。 次のREVERSE SOLIDUSは,後続のVERTICAL LINEを通常文字としている。 その次のVERTICAL LINEは,正規表現OR。 最後の2つのREVERSE SOLIDUSは,1文字の通常文字REVERSE SOLIDUSとなる。 D-フォーマットから正規表現処理に渡される文字列が, このようになっていなければならない。

フィールドフォーマットリストの中では/STRING/の形を使うため, SOLIDUSをエスケープしなければならない。 さらに最後の2つのREVERSE SOLIDUSも2重化しなければならない。 Dフォーマット解析処理でREVERSE SOLIDUSの直前のREVERSE SOLIDUSが取り除かれるためである。

/\/|\||\\\\/

この文字列には、COMMAが使われていないので,このままの形でフィールドリスト中に使用できる。

'foo:/\/|\||\\\\/'

これが,コマンド引数に書かれる形である。 Windowsでは,APOSTROPHEのかわりにQUOTATION MARKを使って"foo:/\/|\||\\\\/"とする。

実は同じ意味のdelimiterを正規表現の[]を使って書くことができる。 この場合'fn:/[\/|\\]/'でよい。 こちらの方が単純で,よい回答である。 上記の例は,説明のために面倒な文字列を使用している。

使用例(入力)

TABで区切られたフィールド"a","b","c"を読み込む:

"a,b,c"

"csv"ファイルからフィールド"a","b","c"を読み込む:

-t "," -z q "a,b,c"

(Csv (comma separated value) フィールドははCOMMAで区切られて, 文字列フィールドではQUOTATION MARKによるクォーティングが使われる。 上記例は,先頭行からデータ行の場合。)

C言語のソースファイルからワードを読み込む:

-t "[^a-zA-Z0-9_]+" -z qQ "words:*"

行の1文字づつをフィールドとして繰り返しで読み込む。

"c:(1)*"

16進数を読み込む:

v::%x

使用例(出力)

Csvファイルへの変換(データ行のみ):

-t "," -z q

入力Dファイルには次のようなデータが入っている:

name:MIYAZAWA
point:67
point:72
point:36

ここから次のような行データに変換するには:

MIYAZAWA: 67, 72, 36

次のようなフィールドフォーマットリストを使う:

"name:/: /,point:/\, /"

(この例では,COMMAがREVERSE SOLIDUSでエスケープしてある。 なお,フィールド"point"のエントリにrepeatはいらないことにも注意せよ。 また,COMMAとSPACEは各"point"フィールドの間には挿入されるが, 行の終端では入らない。)

c-formatの使用: 各値を()でくくって出力する。

value::(%s)

参照

Dintro, D_lsa, DfromLine, DtoLine, Dtie, Duntie, Dpack, Dunpack, Dpr.

AUTHOR

MIYAZAWA Akira


miyazawa@nii.ac.jp
2003-2013