2006/05/14

LaTeX(TeX)で文字列中の文字を置換したい。

cf. Character substitution in TeX
http://hisashim.livejournal.com/276024.html

上記のページにほとんど目的の答えがあるので、これをもう少し汎用にしてみた。
\newcommand{\replacechar}[3]{{\wordbyword{#2}{#3}#1\end }}
\newcommand{\cutoff}[2]{{\relax}}
\def\wordbyword#1#2#3{\ifx#3\end \let\next=\cutoff
\else\ifx#3#1#2%
\else#3%
\fi \let\next=\wordbyword\fi \next{#1}{#2}}
\replacecharの第1引数に文字列、第2引数に置換前の文字、第3引数に置換後の文字を指定する。
いくつか制限がある。判明しているのは以下のとおり。
  • 文字列中のスペースは切り詰められる
  • ほかのコマンドの中で使うには\string\replacechar{foo}{o}{a}などとする必要がある
上記の2番目の制限は、どうやら\defの再帰がトップレベルでしか使えないためっぽい。
同じ理由で、\replacecharを入れ子にして使えない。つまり、文字列中の複数の文字を置換したかったら、同様な方法で新しいマクロを定義する必要がある。たとえば、索引の特殊文字をエスケープするコマンドは、次のようにして作れる。
追記:この例では「"」そのもののエスケープができないので注意。
\newcommand{\indexescape}[1]{{\indexwordbyword#1\end }}
\def\indexwordbyword#1{\ifx#1\end \let\next=\relax
\else\ifx#1{!}"!%
\else\ifx#1{@}"@%
\else\ifx#1{|}"|%
\else#1%
\fi\fi\fi \let\next=\indexwordbyword\fi \next}

\def\myindex#1{\index{\string\indexescape{#1}}}
\myindexの定義に\stringを使っているのも2番目の制限のため。

いちおう、実行例。

replacechar.tex
replacechar.pdf

0 件のコメント: