
別のプログラムへの入力でテキストを作成すると、ターゲットテキストの二重引用符内のすべてのコマンド置換がシェルによって解釈され拡張されることがわかりました。
回答リンクここパラメータの拡張やコマンドの置換を防ぐために単一引用符を使用できることを指摘しています。しかし、コマンド置換を一重引用符で囲んでも、シェルがコマンド置換を拡張するのを防ぐことはできません。
シェルがコマンド置換を実行するコマンドの代わりにテキストとして解釈するのを防ぐ方法は?
デモ
$ echo "`wc -l *`"
現在のディレクトリにあるすべてのファイルの行数を数えます。
$ echo "'`wc -l *`'"
結果は同じです。つまり、現在のディレクトリにあるすべてのファイルの行数を計算します。
修正するこのデモを見ると、一重引用符で引用するのが問題のようです。`
一重引用符と(バックティック)を二重引用符で囲むと思います。文字通りの意味を保つ(つまり、抑制)一重引用符を使用するがコマンド置換を導入するバックティック(つまり、バックティック)の文字通りの意味を維持しません。
マイユースケースでは、他のコマンドの入力を参照する必要があります。これで文書説明する:
一重引用符の中に一重引用符を含めることはできません。
一重引用符コマンド置換が(二重引用符)文字列内にあるときに拡張されるのを防ぐ方法は?バックスラッシュエスケープを使用する以外に、他の方法が必要です。
実際の状況
プログラムがジョブの説明を別々の行に区切るために使用した唯一の方法は、説明を二重引用符で囲むことです。
$ task add "first line doesn\'t say much
Second line says a lot but part of this line does not appear in the resulting description 'truncate -s0 !(temp_file | temp_dir)' truncates all files to 0 bytes as shown by: '`wc -l *`'"
結果の説明:
first line doesn\ -s0 !(temp_file | temp_dir)' truncates all files to 0 bytes as shown by: 0 file1 10 file2 0 directory1 0 directory2 502 file3 123 file4 162 file5 0 directory3
ご覧のとおり
't say much
Second line says a lot but part of this line does not appear in the resulting description 'truncate
説明から欠落しており、シェルで'wc -l *'
コマンドの代替として解釈され、現在のディレクトリにあるすべてのファイルの行番号を説明の一部として含めます。
シェルがtask
(バックスラッシュ)との間の引数部分を削除する原因は何ですか?シェルが上記の単一引用符コマンドの置き換え(例)を解釈するのを防ぐ方法は何ですか?\
-s
'`wc -l *`'
答え1
強い引用のために一重引用符を使用してください。
printf '%s\n' '`wc -l *`'
に渡すパラメータに一重引用符を含めるには、それ自体に別の引用符を使用する必要がprintf
あります。たとえば、次のようになります。'
printf '%s\n' '`wc -l *` and a '"'"' character'
または:
printf '%s\n' '`wc -l *` and a '\'' character'
別の選択肢としては、`
二重引用符の中にバックスラッシュを使用することがあります。
printf '%s\n' "\`wc -l *\` and a ' character"
または`
いくつかの拡張の結果:
backtick='`'
printf '%s\n' "${backtick}wc -l *${backtick} and a ' character"
また注:
cat << 'EOF'
`wc -l *` and a ' character and a " character
EOF
引用を心配せずに任意のテキストを出力します(最初のテキストの周りに引用符がありますEOF
)。
次のようにすることもできます。
var=$(cat << 'EOF'
echo '`wc -l *`'
EOF
)
以下を使用ksh93
またはmksh
最適化できます。
var=$(<<'EOF'
echo '`wc -l *`'
EOF
)
(また動作しますzsh
が、それでもcat
サブシェルで実行されます。)$var
リテラルを含めるために使用されますecho '`wc -l *`'
。
シェルには次のものを含めることがfish
できます。'
'...'
\'
printf '%s\n' '`wc -l *` and a \' character'
しかし、`
とにかくそれは特別ではありません。
printf '%s\n' "`wc -l *` and a ' character"
それも大丈夫です。
rc、es、または with の中に以下をzsh -o rcquotes
挿入できます。'
'...'
''
printf '%s\n' '`wc -l *` and a '' character'
バラより通常の文字のように特殊文字を使用する方法は?詳細については。
答え2
ここに(改行を追加)、
$ task add "first line doesn\'t say much
Second line says a lot but part of this line does not appear in the
resulting description 'truncate -s0 !(temp_file | temp_dir)' truncates
all files to 0 bytes as shown by: '`wc -l *`'"
文字列全体は二重引用符で囲まれているため、コマンドの置き換えやその他の拡張機能はここで実行されます。これはシェルで発生するため、task
文字列を表示する前にバックスラッシュを使用するか、その部分を一重引用符で囲むことでこれを防ぐ必要があります。
例えば
$ printf "%s\n" "...shown by: '\`wc -l *\`'"
...shown by: '`wc -l *`'
だから、
task add "...shown by: '\`wc -l *\`'"
文字列...shown by: '`wc -l *`'
をに渡しますtask
。これは、実行する操作によって異なります。
バックスラッシュを使用したくない場合は、次のように単一引用符で囲みます。
# aaaaaaaaaaaaaaaaBBBBBBBBBBBaaa
$ printf "%s\n" "...shown by: '"'`wc -l *`'"'"
...shown by: '`wc -l *`'
(a
'は二重引用符で囲まれた部分を示し、B
'は一重引用符で囲まれた部分を示します。これは単にシェルコマンドラインから連結されます。一重引用符で囲まれたリテラルは二重引用符で囲まれた文字列内にあります。)
一重引用符とバックスラッシュの場合、二重引用符内の一重引用符をエスケープする必要はありません。実際、バックスラッシュはそのまま残ります。
$ printf "%s\n" "foo'bar"
foo'bar
$ printf "%s\n" "foo\'bar"
foo\'bar
示された内容によると、task
少なくとも最初の一重引用符文字列がパラメータから削除されたようです(削除された部分があるため、その後に単語も追加されます't say much ... 'truncate
)。
これシェル〜するいいえこれはうまくいきます。
$ printf "%s\n" "a 'quoted string' to test"
a 'quoted string' to test
シェルが(バックスラッシュ)との間
task
の引数部分を削除する原因は何ですか?\
-s
おそらくこれを行うシェルではないでしょう。
そして、シェルが上記の一重引用符コマンドの置き換え(例:)
'`wc -l *`'
を解釈するのを防ぐ方法は?
一重引用符ではなく、隣に一重引用符がある二重引用符です。
答え3
次のようにバックスラッシュを使用してバックティックをエスケープできます。
echo "\`wc -l *\`"
答え4
逃げるどの特殊文字が処理されず置換が実行されないようにする任意の文字シーケンス:
- それぞれを
'
次のように交換します。'\''
- 結果の文字列を一重引用符で囲みます。
たとえば、
`wc -l 'my file.txt'`
~になる
'`wc -l '\''my file.txt'\''`'
文字列がで始まるか終わる場合は、'
開始/終了で終わります。''
これは何もしないで削除できますが、そのままにしておくことは有効です(たとえば、文字列を転置したままにします。定義関数は簡単です)。 。