HOME > 電算 > sed でテキストをポストスクリプトに

sed でテキストをポストスクリプトに

(より実用的なものは「SedWord 貧文書入門」を参照)

ごく日常的に、テキストを簡単に印刷したいという場面がよくある。しかし、私の環境では a2ps で日本語が使えず、mpage は、フォントサイズや行送りすら指定できずに何がなんでも版面いっぱいに埋めるという主義なので、使いにくい。sed だけでポストスクリプトファイルを作成できれば、いろんな環境で使えるし、簡便この上ないだろう。なにより必要に応じて改造するのが容易である。そこで、

sed -nf text2ps.sed plain.txt > plain.ps

とやって使える sed スクリプトを書いてみた。(sed は -n オプションとともに起動)

これ→ text2ps.sed

行の折り返しを勝手にやったりはしないので、pr や nkf の -f オプションや、一行字数をそろえる sed スクリプトなんかであらかじめ加工しておく。コーディングシステムは utf-8 を使用すること。

設定ファイルなんかはもちろん無いので、sed スクリプトをエディタで書き換えて調整する。フォント、フォントサイズ、行間隔、1 ページの行数、ペーパーサイズ、左および上マージンを設定することができる。

スクリプトの上のほうから順に、説明をメモしておこう。←自分のため

#!/bin/sed -nf
# usage:    sed -nf text2ps.sed text.txt > text.ps
1 {
h
s/.*/1/
x
}

これはスクリプト中最初に実行され、ホールドスペースに 1 を保存。これを、あとでインクリメントしていき Postscript の DSC コメント中のページ番号として使用。この DSC ページ番号がないと、evince や gv で、ページを後戻りして表示することができない。

1 i\

まずはじめに、以下のテキストを出力する。i コマンドは、\ で隠されない改行までを出力する。

%!PS-Adobe-3.0\
%%BoundingBox: 0 0 595 841            % <-- set paper width and height (A4) here and...\
%%EndComments\
%%BeginProlog\
/paperwidth  595 /paperheight 841 def def\ % <--- ... here again (A4 portrate)\
/fontsize 10 def                      % <--- set fontsize here\
/fontname /Ryumin-Light-UniJIS-UTF8-H def % <--- sef fontname here\
% /fontname /GothicBBB-Medium-UniJIS-UTF8-H def % <--- maybe you like this\
/spacing 5 def                        % <--- set line spacing here\
/leftmargin 80 def                    % <--- set left margin here\
/uppermargin 100 def                  % <--- set upper margin here\
/okuri fontsize spacing add def\
/unijis { fontname findfont fontsize scalefont } def\
/S {save gsave unijis setfont leftmargin paperheight uppermargin sub moveto} def\
/N {currentpoint okuri sub leftmargin exch moveto pop} def\
/E {grestore restore showpage} def\
%%EndProlog\
%%BeginSetup\
<</PageSize [paperwidth paperheight]>>\
%%EndSetup\
%%Page: 1 1\
S

ペーパーサイズは二箇所で重複して指定。一つは Postscript で実際に描画するために使用するためであり、もう一つは DSC コメントで Boundingbox を指定するために使用。後者がないと gv や evince での表示のときに、表示範囲がうまく合わない。手続き S は各ページはじめに、E は終わりに、N は新行の開始時に使うのを、あらかじめ定義しておいたもの。フォントは /Ryumin-Light-UniJIS-UTF8-H を使用。

:a
$ b b
/\([^\n]*\n\)\{44\}/! {               # <--- substitute (lines_per_page - 1) for 44
N
b a
}
:b

1 ページに 45 行を入れるための作業。こちらを参照。埋め込まれた改行が 44 個になるまで、新行を読み込んでいく。以後はパターンスペースに 1 ページぶんのテキストが、改行で区切られた形で入っていることになる。

s/^/(/

ページ冒頭に "(" を挿入する。これは、一行目のテキストをおさめる( )の "(" 。

s/\n/) show \
N(/g

ページ内で改行があるごとに実行される。") show" を前行末に、"N (" を次行頭に書き込む。N は、 current point を左端に移動する手続き名であり、sed の N コマンドではない。

s/$/) show\
E\
/
p

ページの最後で実行される。") show" を挿入し、さらに、手続き名 E を挿入。そのあと p コマンドで、パターンスペースにおさめられた、1 ページぶんのポストスクリプト表現を出力。ここから先、パターンスペースは、次ページの DSC コメントにおけるページ番号の作成に使われる。

g
/\([0-9]*\)[0-8]$/ {
s/\([0-9]*\)8$/\19/
s/\([0-9]*\)7$/\18/
s/\([0-9]*\)6$/\17/
s/\([0-9]*\)5$/\16/
s/\([0-9]*\)4$/\15/
s/\([0-9]*\)3$/\14/
s/\([0-9]*\)2$/\13/
s/\([0-9]*\)1$/\12/
s/\([0-9]*\)0$/\11/
b e
}
/^99*$/ {
y/9/0/
s/^/1/
b e
}
h
s/\(.*[^9][^9]*\)99*$/\1/
s/\([0-9]*\)8$/\19/
s/\([0-9]*\)7$/\18/
s/\([0-9]*\)6$/\17/
s/\([0-9]*\)5$/\16/
s/\([0-9]*\)4$/\15/
s/\([0-9]*\)3$/\14/
s/\([0-9]*\)2$/\13/
s/\([0-9]*\)1$/\12/
x
s/.*[^9]\(99*\)$/\1/
y/9/0/
H
g
s/\n//
:e
h

ページ数をインクリメント。まず、ホールドスペースから現在のページ番号を引出し、それをインクリメントして、パターンスペースに置き、次のインクリメントに備えて新しい数字をホールドスペースにもコピーしておく。インクリメントの仕組みは、こちらを参照。

s/.*/%%Page: & &\
S\
/
$ q
p

ページ番号を含む DSC コメントと手続き名 S を挿入し、次のページを開始する。手続き S はカレントポイントを紙の左上のほうに移動させる。最終行 $ では、これらを出力する必要がないので、q で即刻スクリプトを終了。最終行以外では p でこれらを出力。sed は次のサイクルに入る。

――目次――
HOME雑文写真壁紙馬鹿読書語学
│├英語
│└日本語電算地理
│└白地図ブログ