bashスクリプトがあり、そのうちの1つに次のものが含まれています。
#!/bin/bash
source $(dirname ${BASH_SOURCE[0]})/script.sh
そしてその他の内容は次のとおりです。
#!/bin/bash
source "$(dirname ${BASH_SOURCE[0]})/script.sh"
これらのスクリプトはどのように異なる動作をし、その理由は何ですか?何はい違い?
答え1
引用符のない文字列は次のように保護されています。噴射そしてワイルドカード。また、見ることができますバッシュトラップ #14。
比較する
$ echo $(printf 'foo\nbar\nquux\n*')
foo bar quux ssh-13yzvBMwVYgn ssh-3JIxkphQ07Ei ssh-6YC5dbnk1wOc
そして
$ echo "$(printf 'foo\nbar\nquux\n*')"
foo
bar
quux
*
単語分割が発生すると、最初の文字は区切り文字IFS
(デフォルトでは空白)として機能します。
ほとんどすべての場合に引用符を追加する必要があります。次のようないくつかの例外があります。
単純な(配列ではない)割り当てやステートメントなど、トークン化/グローバル化が発生しない式から
case
。次は安全です。foo=*
foo=${bar}qux${quux}
foo=$(bar "${quux}")
case ${var} in
しかし、これは本当ではありません(あなたが探しているのが文字通りアスタリスク文字を持つ単一の要素である場合)。
foo=( * )
スペースで区切られた文字列でトークンを繰り返すなど、特別にトークン化を実行したい場合(ワイルドカードを無効にする)が、可能であれば配列を使用してください。
答え2
主な違いは、引用されたバージョンがシェルのフィールド分割に影響されないことです。
二重引用符を使用すると、コマンド拡張の結果がsource
コマンドの引数として提供されます。引用符がない場合、デフォルトではIFS
空白、TAB、および改行文字を含む値に応じて複数の引数で区切られます。
ディレクトリ名にこれらのスペースが含まれていない場合、フィールド分割は行われません。
経験的に、コマンドの置換と変数の拡張には二重引用符を使用するのが最善です。
答え3
おそらく最も重要な違いは、スクリプトがあるディレクトリにスペースがあるかどうかです。この場合、最初の行(二重引用符なしの行)は失敗します。これは、引用符で囲まれていない文字列をbash「トークン化」した結果です。
仮想結果dirname ${BASH_SOURCE[0]}
はです/home/j r/bin
。引用符なしで次の行を見てください。
source $(dirname ${BASH_SOURCE[0]})/script.sh
この場合、bashは次のコマンドを表示します。
source /home/j r/bin/script.sh
単語分割後、source
コマンドはスクリプト名/home/j
とスクリプトパラメータを表示できますr/bin/script.sh
。その名前のスクリプトがない可能性が高く、bashはエラーメッセージを返します。
bash: /bin/j: No such file or directory
二重引用符を使用すると、何が起こるのか考えてみましょう。
source "$(dirname ${BASH_SOURCE[0]})/script.sh"
この場合、ソースコマンドは名前付きスクリプトを見つけて/home/j r/bin/script.sh
それを取得しようとします。
完全性のために一重引用符を考えてみましょう。
source '$(dirname ${BASH_SOURCE[0]})/script.sh'
この場合、前の2つとは異なり、dirname
実行されません。ソースコマンドは、リテラル名を使用してコマンドを取得しようとします$(dirname ${BASH_SOURCE[0]})/script.sh
。そのようなファイルが存在しない可能性があり、bashはエラーメッセージを発行します。
bashが二重引用符で囲まれた文字列を処理する方法については、次のトピックで詳しく説明しますman bash
。
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. The characters $ and ` retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or <newline>. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.