シェルに入れ子になった引用符

シェルに入れ子になった引用符

次のコマンドを実行したいと思います。

$ sh -c 'exec python -c "print('$1$2MyString')"'

望ましい結果として'$1$2MyString'

ただし、コマンドを実行すると、次の結果が表示されます。

Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'MysString' is not defined

私が知っている限り、3番目のレベルの引用符を追加すると、実際にコマンドが2つの部分に分割され、シェルは$1$2MyString外部引用符を見て既知の値を変更しようとします。

一重引用符をエスケープすると

$ sh -c 'exec python -c "print(\'$1$2MyString\')"'

次のエラーが発生します。

sh: 1: Syntax error: "(" unexpected

本質的に私の質問は:上記の印刷機能に文字列リテラルを導入する方法はありますか?

答え1

一重引用符で囲まれた文字列内では、一重引用符をエスケープできません。たとえば、以下は不完全な行です。

echo 'boy\'s game'    # Wrong!
>

ただし、さまざまな種類の引用符で囲まれた文字列を連結できます。

echo "boy's"' game'    # Right
boy's game

したがって、引用文"'"などを引用できます。

sh -c 'exec python -c "print('"'"'$1$2MyString'"'"')"'
#     ^-. . . . . . . . . . -^   ^-. . . . . -^   ^--^
#                             ^-^              ^-^

この出力は、呼び出しによって評価が実行されるためMyStringに発生します。リテラルとして使用するには、一重引用符で囲んで明示的に保護する必要があります。$1$2sh$1$2MyStringsh

sh -c 'exec python -c '"'"'print("$1$2MyString")'"'"
#     ^-. . . . . . .-^   ^-. . . . . . . . . .-^

答え2

引用符は入れ子にされません(コマンドの置換を除く)。一重引用符で囲まれた文字列内では、二重引用符は通常の文字であり、引用符としては機能しません。その逆。

Pythonに引数を渡したい場合は、print('$1$2MyString')必要なエスケープを実行できますが、文字列に一重引用符とドル記号の両方が含まれているため、厄介です。つまり、エスケープしなくなった場合は、単一引用符と二重引用符の両方を使用できません。文字列自体にも必要な2番目のレベルの参照を考慮することは言うまでもありません。

または、環境を介して文字列を渡すなどの操作を実行しますsh

code="print('\$1\$2MyString')"  # or
code='print('\''$1$2MyString'\'')'

code=$code sh -c 'exec python -c "$code"'

または、出力を'$1$2MyString'一重引用符で表示する必要がある場合は、Pythonコードは次のようになりますprint("'$1$2MyString'")

code='print("'\''$1$2MyString'\''")'
code=$code sh -c 'exec python -c "$code"'

Pythonコードをファイルに入れる方が簡単かもしれません。

関連情報