回答:
`date`はdate
コマンドの出力に展開されます。ただし、出力に複数の連続したスペース文字がある場所で余分なスペース文字を削除します。(これは、コマンド置換が単語分割の対象であり、echo
コマンドが複数の引数を処理する方法のためです。)
では「`date`」彼らは変数を展開する(「$ PWD」を試してください)とコマンド置換を行いますので、二重引用符は、弱い引用符です。展開の結果は、連続するスペースを含む単一の引数としてecho
コマンドに渡されます。つまり、単語の分割は実行されません。
では「`date`」彼らはその中の変数やコマンド置換の拡大を許可しませんので、単一引用符は、より強力な引用符です。
詳細については、このリンクを参照してください。
date
コマンドと同じものを出力します。
両方
echo `date`
そして
echo "`date`"
日付が表示されます。後者からの出力は、date
単独で実行した場合の出力のように見えます。
ただし、違いがあります。"
引用符で囲まれたものは、単一の引数としてに"
送信されecho
ます。引用符は、コマンド全体の出力を1つの引数としてカプセル化します。echo
引数を間にスペースを入れて順番に出力するだけなので、基本的には同じように見えます。
微妙な違いの例を次に示します。
echo `date`
生成するもの:
Fri Nov 1 01:48:45 EST 2013
しかし:
echo "`date`"
生成するもの:
Fri Nov 1 01:48:49 EST 2013
後の2つのスペースNov
は、引用符なしで1つに縮小されていることに注意してください。これは、シェルがスペースで区切られた各要素を解析し、6つの引数として結果をechoに送信するためです。引用すると、エコーは1つの引数を受け取り、引用符はスペースを保持します。
これは、エコー以外のコマンドでより重要になります。たとえばfoo
、日付と電子メールアドレスの2つの引数を必要とするコマンドを想像してください。
これはそのシナリオで機能します:
foo "`date`" joeuser@example.com
しかし、これは7つの引数を送信することでスクリプトを混乱させます:
foo `date` joeuser@example.com
POSIXシェルで`date`
は、コマンド置換の古代形式です。最新の構文は$(date)
です。
どちらの場合も、date
末尾の改行文字が削除された状態で出力に展開されます(出力にNUL文字が含まれていない場合)。
ただし、二重引用符内およびリストコンテキスト内にない場合(たとえばecho
、あなたの場合のような単純なコマンドへの引数内)、その展開はさらに以下の影響を受けます。
単語の分割:つまり、「date
末尾の改行文字を削除した出力」は、$IFS
変数のデフォルト値(デフォルトではスペース、タブ、改行(およびNULを含むzsh
))に従って複数の単語に分割されます。
たとえば、date
出力がFri 1 Nov 14:11:15 GMT 2013\n
(英語ロケールやイギリス本土のタイムゾーンでよく行われるように)$IFS
現在含まれている:
場合、3つの単語に分割されます:Fri 1 Nov 14
、11
および15 GMT 2013
。
zsh
)であり、上記の分割に起因する各単語は(ワイルドカード文字を探している*
、?
、[...]
いくつかのシェルがよりいるが)、そしてこれらのパターンに一致するファイル名のリストに展開します。例えば、の出力がある場合date
である?%? 33 */*/* UVC 3432
(それは多くの場合、金星のロケールとUVCのタイムゾーンであるように)、そして$IFS
真ん中の文字である現在のディレクトリ内のすべての非隠された3つの文字のファイル名に拡張する、その後、)デフォルト値です%
、33
、すべての非隠された、現在のディレクトリのサブディレクトリのすべての非隠されたサブディレクトリ内のすべての非隠しファイルUVC
と3432
。それが理由です:
$IFS
あなたが分割したい文字に。set +f
、それを無効にします。単一引用符はすべてを引用するため、バックティック文字は文字通りに解釈されます。
例(使用-x
すると、何が起こっているかを簡単に確認できます):
$ bash --norc -x
bash-4.2$ IFS=:
+ IFS=:
bash-4.2$ echo `date`
++ date
+ echo 'Fri 1 Nov 14' 42 '33 GMT 2013'
Fri 1 Nov 14 42 33 GMT 2013
bash-4.2$ echo "`date`"
++ date
+ echo 'Fri 1 Nov 14:42:41 GMT 2013'
Fri 1 Nov 14:42:41 GMT 2013
bash-4.2$ cd /lib/modules
+ cd /lib/modules
bash-4.2$ export TZ=UVC LC_ALL=vs_VS
+ export TZ=UVC LC_ALL=vs_VS
+ TZ=UVC
+ LC_ALL=vs_VS
bash-4.2$ unset -v IFS # get the default behaviour
+ unset -v IFS
bash-4.2$ echo `date`
++ date
+ echo '?%?' 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
?%? 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
bash-4.2$ echo "`date`"
++ date
+ echo '?%? 33 */*/* UVC 3432'
?%? 33 */*/* UVC 3432
出力にNUL文字が含まれる場合、動作はシェルごとに異なります:一部はそれらを削除し、一部は最初のNUL文字で出力を切り捨て、zsh
それらを保持しますが、外部コマンドはNULを含む引数を取ることができないことに注意してください
`date`を使用すると、コマンドの置換後に単語の分割が行われるため、日付の出力が複数の単語に分割されます。
「 `date`」を使用すると、二重引用符の間にコマンド置換があるため、日付の出力が1つの単語/パラメーターとして取得されますが、出力はそれ以上解析されません。以下の例では、「$ i」のような変数展開でも同じことが有効です。
「 `date`」を使用すると、単一引用符の間にコマンドの置換がないため、リテラルの「date」が取得されます。
おそらく、3つのフォームの違いはこの方法でより明確になります。
> for i in `date`; do echo "$i"; done
Fr
1.
Nov
12:25:30
CET
2013
> for i in "`date`"; do echo "$i"; done
Fr 1. Nov 12:25:38 CET 2013
> for i in '`date`'; do echo "$i"; done
`date`