• ベストアンサー

sed で \ を含む文字列に置換

現在、非常に多数のドキュメントの整形を LaTeXを使って自動的に行っています。 問題となっている処理のエッセンスを抜き出すと次のようなもので、テンプレートファイル中の __PATTERN__ という文字列を、その都度指定する文字列($string)に置換した後にplatexでコンパイルする、という流れです。 ---------- #!/bin/bash sed "s/__PATTERN__/$string/" < template.tex > document.tex platex document.tex ---------- 問題は、$string に '_'(アンダーバー)が含まれるケースで、platexのコンパイルでエラーが発生します。 これを回避するには、'_' を '\_' に置換する必要がありますが、上記処理の前に、$string 中の '_' を '\_' に置換する処理を加えても、上記処理の段階で '\' が消えてしまいます。 肝は sed でのエスケープのやり方だと思うのですが、どうにもうまく行きませんので、お知恵を拝借できればと思います。 なお、tex ファイル中、__PATTERN__ は、他のコマンドの引数内で使用されているため、\verb+ + で囲むという手段も使えません。

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

""中なら \ は \\ とクォートしないとダメですね. ちなみに「$string 中の '_' を '\_' に置換する」のはどんな処理ですか?

astronaut
質問者

補足

ありがとうございます。自己解決しました。 > ""中なら \ は \\ とクォートしないとダメですね. とのご回答のとおり、最後の置換で \ を一つ残すためには、事前に $string 中の '_' を '\\_' に置換する必要があり、このためには、 sed 's/_/\\\\\\\\_/g'` と、バックスラッシュを8個並べれば良いようです。 4個でいいと思っていてうまくいかないので質問したのですが、これで解決です。どうして8個必要になるのかがイマイチ理解できていませんが。

その他の回答 (1)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

>どうして8個必要になるのか エスケープを処理するステップが何回もあるからです。 sed "s/__PATTERN__/$string/" なので、$string に8個の '\' があったとすると、 ・sed に渡されるのは4個の '\' になります。(1回目) ・さらに置換ルーチンに渡されるときに2個になります。(2回目) ・置換ルーチンがその2個の'\' を1個の'\'と解釈します。(3回目) →出力されるのは1つ というわけです。

関連するQ&A