sedで&を含む変数をワンライナーで変換するときのエスケープのお話


目的

  • 数字実体とか&を含む文字列をsedで変換したい時があります。
  • このねたはかなりネットに情報があるので新規性はないのですが、きっとまた忘れるのでじぶんのために書いておきます

コード

  • いきなりコードです。
# h=1.5mの数字実体です
hoge="h=1.5m"
# 変数を埋め込むための特定の文字列(例えば%1)をファイルに埋め込みます
cat << EOF > fuga
高さは%1
EOF
# コードです
cat fuga | sed 's|%1|'$( sed "s|\&|\\\&|g" <<< $hoge)'|'
高さはh&#61;1&#46;5m
# うまくいきました

- これをHTMLでそのまま表示させると数字実体は文字に変換されて人に優しい情報に変換されます。

解説

  • このワンライナーはsedを二重で使っているのですが、一つ目のsedの置換後の文字列を変数$hogeから&をエスケープします
  • ちなみに<<<は変数をコマンドに渡すbash機能です。
  • sedは変換後の文字指定に&があると変換前の文字列を参照します。そのため\&とエスケープする必要があります。
  • ただし、参考文献の場合は直接変換なので\\&を2つでいいのですが、今回は$()の中でsedを使っているので&のエスケープは\\\&とひとつ多くしなければなりません。
  • それと'"を使い分けて混乱がないようにしています。
  • 数字実体は、shellでコマンドインジェクションの脅威を減らすとか、ユーザ入力の不定形な文字列であってもホワイトスペース区切りとできるのでcgiにもちいるには便利です。
  • shell系の知識は数十年有効だったしきっとこれからもそうでしょうから、どんな言語よりも教育コストが低いのかもしれないなと思うこの頃です

参考文献

sed で変数に代入されている&等のメタ文字のエスケープ処理を行いたい