Bashスクリプトで引用符なしで変数をレンダリングするには?

Bashスクリプトで引用符なしで変数をレンダリングするには?

次のスクリプト:

$ cat runme01.sh 
#!/bin/bash

A=myval
B=$A/{fix}
C=$A/fix

set -xT

echo $B
echo $C

実行すると、以下が印刷されます。

$ ./runme01.sh 
+ echo 'myval/{fix}'
myval/{fix}
+ echo myval/fix
myval/fix

ご覧のとおり、変数はB一重引用符で渡され、変数は一重引用符なしで渡されます。echoC

おそらく矯正器なのでそうです。

私はいつも引用符なしで渡したいと思います。どうすればいいですか?

答え1

トレース出力を純粋に情報提供として解釈しないでください。これはデバッグ出力です。

myval/{fix}一重引用符内の中括弧は、シェルが特定の文字列を別のものとして解釈する以外にあまり意味がないことを示しています。特に、はいいいえ文字列が引用されたことを意味します! 中かっこが次のようになるため、シェルはトレース出力に一重引用符を追加します。時々ただし、この場合は特別ではありません(実際の支柱拡張を使用しないため)。

ここでも同じことが起こります(空のディレクトリで実行)。

$ echo *
+ echo '*'
*

私のコマンドに引用符を使用しないので、*シェル努力するそれを延長するため。何も拡張されないので、拡張されていないままです。トレース出力を生成するコードは、*文字列のaを調べてそれを引用します。これは、印刷される文字列の文字に基づいて一重引用符を機械的に追加することに基づいており、コマンドや結果に何の影響も与えません。

これをもう一度説明すると、次のようになります。

$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Jun 14 20:15 "filename"
-rw-r--r--  1 kk  wheel  0 Jun 14 20:13 'filename'
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 *
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 **
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 123
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 file
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 long name
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 {}
$ echo *
+ echo '"filename"' ''\''filename'\''' '*' '**' 123 file 'long name' '{}'
"filename" 'filename' * ** 123 file long name {}

つまり、文字列の特定の文字が原因でトレース出力を生成するコードが失敗しますbash。また、シェルは文字列から一重引用符をエスケープします。

これをまたは以下とdash比較してくださいpdksh

$ echo *
+ echo "filename" 'filename' * ** 123 file long name {}
"filename" 'filename' * ** 123 file long name {}

これらの特定のシェルは引用符を追加しません(または単一引用符をエスケープします)。実際には重要ではありません。ただデバッグ出力にすぎません。


シェルが文字列に対してトークン化とファイル名の生成を明示的に必要としない限り、常に二重引用符で囲まれた変数拡張を使用してください。

二重引用符は必ずしもそうではありません。必要しかし、不要な文脈を覚えるよりも常に二重引用符を使用することを覚えておくのは簡単です。

スクリプトが修正されました:

#!/bin/bash

A=myval
B="$A/{fix}"
C="$A/fix"

set -xT

printf '%s\n' "$B"
printf '%s\n' "$C"

これにより、値に関係なく常にこれらの値を取得して$B標準出力に印刷できます。$C元のコードで$Awasを*使用し$B$C引用符を使用しない場合は、一致するファイル名を取得できます。

トレース出力はまだmyval/{fix}このコードを使用して文字列を引用します。心配しないでください。これは何の意味もありません。ただデバッグ出力を助けるためのシェルだけです。

関連:

答え2

一度設定するとIFS=$'\n'単語の区切りは発生せず、引用符なしですべての操作を実行できます。

セキュリティ上のリスクがあるかもしれませんが、私が知っている限り、それはAPI用であるため、とにかくbashスクリプトを使用しません。

一部の人はxやyでは動作しないと言いますが、動作します。

関連情報