sed 特殊文字置換はシェルスクリプトでは機能しません

sed 特殊文字置換はシェルスクリプトでは機能しません

ユーザーの入力を受け入れ、すべての特殊文字を「\」+文字に置き換えるスクリプト「test.sh」を作成したいと思います。私のスクリプト:

#!/bin/bash
echo 'input='"$1"
arg=`echo "$1" | sed 's:[]\[\^\$\.\*\/]:\\&:g'`
echo 'modified input='"$arg"

私のコマンドは、特殊文字のない文字列 "xy"で動作します。端末で次のコマンドを実行します。

test.sh xy

私は得る:

input=xy
modified input=xy

しかし、これを実行すると、次のようになります。

test.sh x.y

私は得る:

input=x.y
modified input=x&y

このスクリプトがなぜ機能しないのか理解できません。私は次のことを期待しています:

input=x.y
modified input=x\.y

問題はこのsedコマンドにあると思いますが、どこにいるのかわかりません。

sed 's:[]\[\^\$\.\*\/]:\\&:g'

答え1

グループを正しくキャプチャしていないようです。この試み?

sed 's:\([]\[\^\$\.\*\/]\):\\\1:g'

編集:気にしないでください。 &の関連性がわかりません。問題は、構文解析とサブシェル渡しのため、代替からスラッシュをさらにエスケープする必要があることです。

sed 's:[]\[\^\$\.\*\/]:\\\\&:g'

また、バックティックの代わりに$(command)を使用すると、追加の\は必要ありません。

答え2

したがって、アクションは、文字列内のsedすべての特殊文字(私が追加した文字として定義されている)をエスケープする代替文字を作成することです。[]^$.*/\

代替品は次のとおりです。

s/[][\^$.*/]/\\&/g

[...]実際にセットの文字をエスケープする必要はありません(文字通り\処理されるため、できないそこから何でも脱出してください)、私たちが確認する唯一のことは、これが]まさに最初にあることです。

したがって、スクリプト(シェル関数で再構築または変更)は次のようになります。

function escape
{
    printf '%s\n' "$1" | sed 's/[][\^$.*/]/\\&/g'
}

テスト:

$ escape 'hello world'
hello world

$  escape '*.*'
\*\.\* 

$ escape '\/'
\\\/

$ escape '/\'
\/\\

$ escape 's/[][\^$.*/]/\\&/g'
s\/\[\]\[\\\^\$\.\*\/\]\/\\\\&\/g

関連情報