エスケープされた文字列をエコーする方法

エスケープされた文字列をエコーする方法

Bourne Shellで$を含むエスケープ文字列をエコーする方法は?

user@server:~$ cat test.sh 
#!/bin/sh
echo $1

user@server:~$ ./test.sh \$sad\$test
$sad$test

次のようにエスケープされたバージョンを返したいと思います。

user@server:~$ ./test.sh \$sad\$test
\$sad\$test

私はsedとawkを使っていくつかのトリックを試しましたが、成功しませんでした。どんな指針でも大変感謝いたします。

ベストアンサー1

文字列が「シェル引用」として表示されることを想定しています。

これ印刷機能組み込みコマンドはケシ強く打つ扱いにくいすべて%q書式指定子を理解します。実際の出力は正規化されず、入力文字列によって異なります(下記参照)。出力形式の変更により、あるシェルの出力を別のシェルで使用できなくなる可能性があります(特に、ターゲットシェルが機能が少ないシェルの場合)。禁煙健康増進協会スプリント、等。 )。

扱いにくいパラメータ拡張から直接引用符を生成する機能もサポートされています。

echo "${(q)1}"    # backslashes, with $'' for unprintable/invalid characters
echo "${(qq)1}"   # single quotes
echo "${(qqq)1}"  # double quotes
echo "${(qqqq)1}" # $'' quoting

「自分でやりたい」場合は、最も簡単で信頼できる方法は、独自の一重引用符を生成することです。単純なアルゴリズムは次のとおりです。

  1. 一重引用符をシーケンスに変更します'\''
  2. 結果を一重引用符で囲みます。

一重引用符は完全にliteral1なので、Bourneなどのシェルで動作します。一重引用符を表すには、現在の一重引用符の範囲を終了し、バックスラッシュでエスケープされた一重引用符を指定し、文字列の残りの部分に一重引用符を再使用します。上記のアルゴリズムは、連続した一重引用符と文字列の先頭と末尾にある一重引用符を処理すると効率が悪くなりますが、非常に安定しており、実装が非常に簡単です。

1他の言語の一重引用符は通常完全に文字通りではありません(少なくとも一般的に制限されたバックスラッシュエスケープを許可します)。これが、すぐに生成される引用形式のすべての引用規則を理解することが重要な理由です(つまり、引用されたテキストがどの言語/コンテキストで使用されるか)。


printf %q以下は、ローカルにインストールされたシェルのいくつかの例です。

for s in /bin/ksh {,/opt/local}/bin/bash {,/opt/local}/bin/zsh
do
  "$s" --version | head -1
  "$s" -c 'printf "%q\n" "$@"' - \$sad\$test \'mixed\ quotes\" back\`tick
  echo
done

出力:

  version         sh (AT&T Research) 1993-12-28 s+
'$sad$test'
$'\'mixed quotes"'
'back`tick'

GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

GNU bash, version 4.2.10(2)-release (i386-apple-darwin10.7.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

zsh 4.3.9 (i386-apple-darwin10.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

zsh 4.3.12 (i386-apple-darwin10.7.0)
\$sad\$test
\'mixed\ quotes\"
back\`tick

私たちは見ましたケシ一重引用符で引用することを「好む」ように見えますが、$''場合によってはこの形式を使用します。他のシェルは主にバックスラッシュエスケープを使用しているようです($''特定の文字がある場合はそれを使用しますが)。

おすすめ記事