PERLFORM(1)              USER COMMANDS                PERLFORM(1)



NAME
     perlform - Perl のフォーマット文

DESCRIPTION
     Perl は、単純なレポートやチャートを作成するお手伝いができま
     す。 これを簡単にするために、Perl では、印字された時にどの
     ように見えるかに近い形で、コードの中で出力ページをレイアウト
     できます。 Perl はまた、1 ページに何行入るか、現在何ページ
     めか、いつページヘッダを出力するかといったことのめんどうをみ
     てくれます。 使用されるキーワードは FORTRAN から持ってきた
     もので、宣言に format 文を用い、実行に write() を使います。
     perlfunc manpage で formlinewrite の項を参照してください。
     幸い、レイアウトは BASIC の PRINT USING 文のようなものより読
     みやすいものです。 安上がりな nroff(1) と考えてください。

     フォーマットは、パッケージやサブルーティンと同じく、実行文で
     はなく、宣言文ですから、プログラムのどこにおいてもかまいませ
     ん。 (しかしながら、普通は 1 か所にまとめておいた方が良いで
     しょう。) フォーマットは Perl の他の「型」とは別に名前空間
     がとられます。 このことは、"Foo" という名前の関数を持ってい
     るとき、それは、"Foo" という名前のフォーマットを持っているの
     とは違うということです。 しかし、あるファイルハンドルに対し
     て付随するフォーマットのデフォルトの名前は、そのファイルハン
     ドルの名前と同じものです。 つまり、STDOUT に対するデフォル
     トのデフォルトのフォーマットは "STDOUT" であり、ファイルハン
     ドル TEMP に対するデフォルトのフォーマット名は "TEMP" だとい
     うことです。 これらは同じように見えますが、違うものです。

     出力レコードのフォーマットは以下のように宣言します:

         format NAME =
         FORMLIST
         .

     NAME を指定しないと、"STDOUT" というフォーマットが定義されま
     す。 FORMLIST は行の並びからなり、それぞれの行は次の 3 つの
     どれかになります:

     1.  コメント。 行頭に # を置くとその行はコメントとして扱わ
         れます。

     2.  ピクチャ行。 出力する行のフォーマットを 1 行単位で示し
         ます。

     3.  引数行。 先行するピクチャ行に埋め込む値を示します。

     ピクチャ行は、ある種のフィールドが、その行に値を埋め込むのに
     使われる他は、まったく見た目の通りに印字されます。 ピクチャ
     行の各々のフィールドは、"@" や "^" で始まるようになっていま
     す。 ピクチャ行では、いかなる形でも変数の展開は行なわれませ
     ん。 "@" フィールド (配列の "@" と混同しないこと) は、通常
     のフィードで、"^" フィールドが複数行に渡るテキストのブロック



Perl manpages Last change: Release 5.0 Patchlevel 00            1






PERLFORM(1)              USER COMMANDS                PERLFORM(1)



     を作るために使われます。 フィールドの長さは、"@" や "^" の
     あとに "<" や ">" や "|" を必要な数だけ並べることで表わし、
     それぞれ、左づめ、右づめ、センタリングを表わします。 もし、
     値がフィールドをはみだす場合には、切り捨てられてしまいます。

     右づめの別の形式として、数値フィールドを示す、"#" (と "." も
     可) を使うこともできます。 この方法で、小数点の位置を揃える
     ことができます。 こういったフィールドに与えられる値に改行が
     含まれていると、その改行までのテキストが印字されます。 もう
     1 つ "@*" というフィールドを使うと、値の切捨てを行なわずに、
     複数行にわたって印字するために使用するようにできます。 この
     フィールドを使う場合には、同じ行に別のフィールドを指定できま
     せん。

     各フィールドへの値は、次の行に、ピクチャフィールドと同じ順番
     で指定します。 値を示す式は、コンマで区切られている必要があ
     ります。 式はすべて、その行が評価される前に、リストコンテキ
     ストで評価されますので、1 つのリスト式が複数のリスト要素を作
     るようにもできます。 式は、中括弧で括って、複数行にすること
     もできます。 もし、そのようにするときは、最初の行の最初のト
     ークンを、開き中括弧にしなければなりません。

     "@" ではなく、"^" で始まるピクチャフィールドは、特別な扱いを
     受けます。 "#" を使ったフィールドでは、値が未定義の場合に、
     空白となります。 他のタイプのフィールドでは、"^" はある種の
     充填モードになります。 値として指定できるものは、任意の式で
     はなく、テキスト文字列が入ったスカラ変数名でなければなりませ
     ん。 Perl はそのフィールドに入るだけのテキストを詰め込んで、
     変数内の文字列の先頭から、その分を切り落とします。 次にその
     変数が参照されるときには、残りの部分のテキストが印字できるこ
     とになります。 (そうです、このことは変数自身が write() の実
     行中に変更され、もとには戻らないということです。) 普通は、
     テキストを矩形に表示するように、フィールドを縦に積むような形
     で使われます。 一番最後のフィールドを "..." という文字列で
     終わらせておくと、表示するテキストがその最後のフィールドにも
     収まりきらなかったときに、そのまま "..." が出力されます。
     $: (English モジュール使用時は $FORMAT_LINE_BREAK_CHARACTERS)
     という変数に文字列を設定すると、出力する文字列の中に、この変
     数内に設定した文字列中の 1 字が見つかったときに改行するよう
     になります。

     "^" フィールドを使うと可変長のレコードが作れます。 フォーマ
     ットされるテキストが短ければ、行のどこかに "~" をおくことで
     空行の出力をサプレスすることができます。 出力時には、"~" は
     空白に変換されます。 "~" を 2 つ並べて書くと、すべてのフィ
     ールドに入れられる値が尽きてしまうまで、そのピクチャ行と引数
     行を繰り返して使用します。 (もし、"@" タイプのフィールドを
     使うならば、与える式は永久に同じ値を出すことの無いようにしな
     いといけません。)

     ページ先頭フォーマットの処理はデフォルトでは、現在のファイル
     ハンドル名に "_TOP" をつなげた名前のフォーマットで行なわれま



Perl manpages Last change: Release 5.0 Patchlevel 00            2






PERLFORM(1)              USER COMMANDS                PERLFORM(1)



     す。 これは、各々のページの先頭で使われます。 perlfunc
     manpage の write() の項を参照してください。

     例:

      # /etc/passwd ファイルについてのレポート
      format STDOUT_TOP =
                              Passwd File
      Name                Login    Office   Uid   Gid Home
      ------------------------------------------------------------------
      .
      format STDOUT =
      @<<<<<<<<<<<<<<<<<< @||||||| @<<<<<<@>>>> @>>>> @<<<<<<<<<<<<<<<<<
      $name,              $login,  $office,$uid,$gid, $home
      .

      # バグ報告書からのレポート
      format STDOUT_TOP =
                              Bug Reports
      @<<<<<<<<<<<<<<<<<<<<<<<     @|||         @>>>>>>>>>>>>>>>>>>>>>>>
      $system,                      $%,         $date
      ------------------------------------------------------------------
      .
      format STDOUT =
      Subject: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
               $subject
      Index: @<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
             $index,                       $description
      Priority: @<<<<<<<<<< Date: @<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                $priority,        $date,   $description
      From: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            $from,                         $description
      Assigned to: @<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                   $programmer,            $description
      ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                           $description
      ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                           $description
      ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                           $description
      ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                           $description
      ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<...
                                           $description
      .

     同じ出力チャネルに print() と write() を混ぜて使うことも可能
     ですが、$- ($FORMAT_LINES_LEFT) を自分で調整する必要がありま
     す。






Perl manpages Last change: Release 5.0 Patchlevel 00            3






PERLFORM(1)              USER COMMANDS                PERLFORM(1)



     フォーマット変数

     その時点でのフォーマット名は、変数 $~ ($FORMAT_NAME) に入れ
     られており、ページ先頭フォーマットは、$^ ($FORMAT_TOP_NAME)
     に入れられています。 ページ番号は、$% ($FORMAT_PAGE_NUMBER)
     に、ページあたりの行数は $= ($FORMAT_LINES_PER_PAGE) に入っ
     ています。 そのファイルハンドルに対して出力を自動フラッシュ
     するか否かは、$| ($OUTPUT_AUTOFLUSH) に入れられています。
     (先頭ページ以外の) ページの先頭の前に出力する文字列は、$^L
     ($FORMAT_FORMFEED) に蓄えられます。 これらの変数は、ファイ
     ルハンドルごとに設定されますので、特定のファイルハンドルのも
     のを変更するには select() する必要があります:

         select((select(OUTF),
                 $~ = "My_Other_Format",
                 $^ = "My_Top_Format"
                )[0]);

     汚いですか? でも、普通のイディオムなので、見つけたときには
     驚かないでください。 少なくとも以前のファイルハンドルを保持
     するのに一時変数を使うことができます。 (読みやすいばかりで
     なく、デバッガでステップ実行するときに式の途中で、中間的な状
     態を用意できることになりますから、一般にはこちらの方がずっと
     良いでしょう):

         $ofh = select(OUTF);
         $~ = "My_Other_Format";
         $^ = "My_Top_Format";
         select($ofh);

     English モジュールを使えば、変数名を読むことさえできます:

         use English;
         $ofh = select(OUTF);
         $FORMAT_NAME     = "My_Other_Format";
         $FORMAT_TOP_NAME = "My_Top_Format";
         select($ofh);

     しかし、意味不明の select() がまだ残っています。 FileHandle
     モジュールを使ってください。 小文字のメソッドを使って、特殊
     変数をアクセスすることができるようになります:

         use FileHandle;
         format_name     OUTF "My_Other_Format";
         format_top_name OUTF "My_Top_Format";

     ずっと良いでしょう !

NOTES
     引数行には、(^ フィールドに対してではなく、@ フィールドに対
     して) 任意の式が許容されますから、もっと込み入った処理には、
     sprintf() や独自の関数などに任せることもできます。 たとえば:



Perl manpages Last change: Release 5.0 Patchlevel 00            4






PERLFORM(1)              USER COMMANDS                PERLFORM(1)



         format Ident =
             @<<<<<<<<<<<<<<<
             &commify($n)
         .

     実際に @ や ^ をフィールドに表示するには、以下のようにします:

         format Ident =
         I have an @ here.
                 "@"
         .

     テキスト全体をセンタリングするには、このようになります:

         format Ident =
         @|||||||||||||||||||||||||||||||||||||||||||||||
                 "Some text line"
         .

     「どんな幅であっても、右端に寄せるようにしたい。」というよう
     な要望に答える方法は組み込まれていません。 表示する場所を必
     ず指定する必要があります。 窮余の策としては、現在のカラム数
     に基づいて、その場でフォーマットを作って、eval() することが
     できます:

         $format  = "format STDOUT = \n";
                  . '^' . '<' x $cols . "\n";
                  . '$entry' . "\n";
                  . "\t^" . "<" x ($cols-8) . "~~\n";
                  . '$entry' . "\n";
                  . ".\n";
         print $format if $Debugging;
         eval $format;
         die $@ if $@;

     これは、以下のようなフォーマット文を生成します:

      format STDOUT =
      ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
      $entry
              ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
      $entry
      .

     fmt(1) のようなプログラム:

      format =
      ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
      $_
      .





Perl manpages Last change: Release 5.0 Patchlevel 00            5






PERLFORM(1)              USER COMMANDS                PERLFORM(1)



      $/ = '';
      while (<>) {
          s/\s*\n\s*/ /g;
          write;
      }


     フッタ

     $FORMAT_TOP_NAME には、その時点のページ先頭フォーマット(ヘ
     ッダフォーマット)の名前が納められていますが、フッタに対して
     自動的に同じことをするための、対応する機構は用意されていませ
     ん。 フォーマットを評価するまでは、どのくらいの大きさになる
     のかがわからないことも、大きな問題と言えます。 これは、Todo
     のリストに入っています。

     1 つの方法をあげておきます: 固定サイズのフッタであれば、
     write() を行なう前ごとに $FORMAT_LINES_LEFT をチェックして、
     必要なときにフッタを print することで、フッタを付けることが
     できます。

     もう 1 つ別の方法です: open(MESELF, "|-") を使って、自分自
     身にパイプを open し (perlfunc manpage の open() の項を参照
     してください)、常に STDOUT の代わりに MESELF に write() する
     ようにします。 チャイルドプロセス側では、STDIN からの入力を
     フォーマットし直して、好きな形にヘッダやフッタを整えるように
     します。 簡単とは言えませんが、実行は可能です。

     内部のフォーマット動作へのアクセス

     フォーマット機構に対する低レベルのアクセスのため、formline()
     を使い、$^A ($ACCUMULATOR) を直接アクセスすることができます。

     たとえば、

         $str = formline <<'END', 1,2,3;
         @<<<  @|||  @>>>
         END

         print "Wow, I just stored `$^A' in the accumulator!\n";

     もしくは、printf() に対する sprintf() のような write() に対
     するサブルーティン swrite() を作るため:

         use English;
         use Carp;
         sub swrite {
             croak "usage: swrite PICTURE ARGS" unless @ARG;
             local($ACCUMULATOR);
             formline(@ARG);
             return $ACCUMULATOR;
         }



Perl manpages Last change: Release 5.0 Patchlevel 00            6






PERLFORM(1)              USER COMMANDS                PERLFORM(1)




         $string = swrite(<<'END', 1, 2, 3);
      Check me out
      @<<<  @|||  @>>>
      END
         print $string;

     のようにします。


WARNING
     format の実行中には、グローバルな変数と local() で宣言された
     動的スコープの変数だけが見えます。 my() で宣言された字句ス
     コープの変数は、format と同じスコープにあるとはみなされず、
     使用することができません。








































Perl manpages Last change: Release 5.0 Patchlevel 00            7