それではSCSHが実際に役立つ例を紹介しよう。以前、latex2htmlプログラムを使用してLaTexファイルからHTMLファイルを生成しなければならないことがあった。ところが困ったことに、引数を指定せずにlatex2htmlを実行するとナビゲーションバー用の画像のパス名が絶対パス名として生成された。生成したHTMLを表示するWebブラウザは/usr/lib/latex2html/icons/の中で画像を探そうとするのだが、このWebページをインターネット経由で閲覧する場合や、latex2htmlをインストールしていない場合には画像を見つけることができない。
解決方法は、(HTMLファイルと一緒に配布するように)ナビゲーションバー用の画像をパッケージにまとめて、HTMLファイル内で絶対パス名になっている個所を見つけ出して置換することだった。そのため、まずlatex2htmlに1つの引数を指定して「latex2html testdoc.latex」として実行した。これによりtestdocという名前のディレクトリが作成されて、そのディレクトリの中にHTMLファイルが生成された。
<!--ここまでHTMLファイルの内容-->
<!--ナビゲーションバー-->
<A NAME="tex2html2"
HREF="https://www.itmedia.co.jp/enterprise/articles/0805/27/node1.html"
<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
SRC="https://image.itmedia.co.jp/enterprise/articles/0805/27/file:/usr/lib/latex2html/icons/next.png"></A>
<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
SRC="https://image.itmedia.co.jp/enterprise/articles/0805/27/file:/usr/lib/latex2html/icons/up_g.png">
<!- この後もHTMLが続く ->
ここで「file:/usr/lib/latex2html/icons/ 」となっている個所を見つけ出して、別のパスか空の文字列に置換する必要がある。わたしの場合は空の文字列に置き換えて、使いたいアイコン画像をHTMLファイルと一緒に配布することにした。この単純作業を行うためのコードを以下に示す。
#!/usr/bin/scsh -s
!#
(define replace (rx "file:/usr/lib/latex2html/icons/"))
(define (read-lines) (port->string-list (current-input-port)))
(define (replace-line line)
(regexp-substitute/global (current-output-port) replace line 'pre 'post)
(newline))
(for-each (lambda (fname)
(let ((lines (with-input-from-file fname read-lines)))
(rename-file fname (string-append fname ".bak"))
(with-output-to-file fname
(lambda () (for-each replace-line lines)))))
(glob "*.html"))
このコードは、SCSHの基本的な使い方を示す好例だ。最初の行は、使用するインタプリタをシェルに伝えるためのシェバング行だ。次の3行では、置換したい正規表現、現在の入力ポートを文字列のリストに変換する関数、正規表現にマッチした文字列を空の文字列で置き換える関数をそれぞれ定義している。この例の正規表現には特別な点は特になくて、単にマッチさせる文字列を指定しているにすぎない。
続く行ではfor-each関数を呼び出して、「*.html」に該当するすべてのファイルに対してlambdaで定義する関数を適用している。lambdaで定義した関数の中では、letフォームを使用して、ファイルfnameから読み取った行のリストを変数linesに代入している。この関数の後半部分では、バックアップのためにファイルをファイル拡張子「.bak」をつけ足したファイル名に改名している。その後いよいよ、文字列の置換を行っている。
(with-output-to-file fname
(lambda () (for-each replace-line lines)))))
この部分では、まずファイルfnameを開いて、次に変数lines内の各文字列について関数replace-lineを適用することで、すでに指定した正規表現に対するマッチを見つけて置換し、開いているファイルに行を出力している。
Copyright © 2010 OSDN Corporation, All Rights Reserved.