- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- シェルスクリプト/sedでバックスラッシュを置換する際の注意点 へ行く。
- 1 (2006-12-27 (水) 20:03:42)
sedでバックスラッシュを置換する際の注意点
シェル展開の挙動について
正規表現を'(シングルクォート)でくくる場合、置換文字列「\\」がシェル展開されずにsedに伝わる。sedは「\\」を「\」と解釈し、結果を表示する。
> echo "[/]" | sed -e 's/\//\\/' [\]
正規表現を"(ダブルクォート)でくくる場合、置換文字列「\\\\」はシェル展開されて「\\」に変わる。sedは「\\」を「\」と解釈し、結果を表示する。
なお、「\\\」をシェル展開しても「\\」になる。「\\\\\」をシェル展開すると「\\\」に変わる。この挙動はしっくりこないが、基本的に「\\\\」を「\\」に展開する方針を採った方が分かりやすいだろう。
> echo "[/]" | sed -e "s/\//\\\\/" [\]
正規表現にシェル変数を使うには?
正規表現に与える文字列では「\」をエスケープしなければならない。「/etc/passwd」に対して「/etc」を「/tmp」に置換するようなケースを考えてみる。
Perlで言えば以下のようにすることで、「/tmp/passwd 」と表示される
$etc_passwd = "/etc/passwd"; $etc_passwd =~ s#/etc#/tmp#; print $etc_passwd;
まず「/etc」を「\/etc」とする。
etc="/etc" escaped_etc=`echo $etc | sed -e 's/\//\\\\\//g'` echo $escaped_etc
「\\\\\/」は前半4文字と後半2文字で分けて考える。
まず前半4文字「\\\\\」を考える。最初にバッククォートによるシェル展開で「\\\\」が「\\」に展開される。次にsedによる解釈で「\\」が「\」に変わる。
次に後半2文字「\/」を考える。最初にバッククォートによるシェル展開で「\/」が「/」に展開される。次に「/」はsedに文字通り解釈される。
etc_passwd="/etc/passwd" tmp_passwd=`echo "$etc_passwd" | sed -e "s/^$escaped_etc/\/tmp/"` echo $tmp_passwd
続き、実際にetcをtmpに置換するsedを考える。
$escaped_etcにはエスケープされた「\/etc」が入っている。バッククォートによるシェル展開で「/etc」になり、sedはそれを文字通り解釈する。
また、「\/tmp/」もバッククォートによるシェル展開で「/tmp」になり、sedはそれを文字通り解釈する。
以上で、「/etc/passwd」が「/tmp/passwd」に置換された。全部をシェルスクリプトにすると以下の通り。
#!/bin/sh etc="/etc" escaped_etc=`echo $etc | sed -e 's/\//\\\\\//g'` etc_passwd="/etc/passwd" tmp_passwd=`echo "$etc_passwd" | sed -e "s/^$escaped_etc/\/tmp/"` echo $tmp_passwd