web-dev-qa-db-ja.com

echo $(cal)とecho "$(cal)"の違い

Linuxでecho $(cal)echo "$(cal)"を使用していますが、図のように異なる結果が得られます。この場合、二重引用符は_$_に干渉しないはずです。したがって、echo "$(cal)"と比較してその水平スタイルをecho $(cal)に与えるものは何ですか。

結果は次のとおりです。

Screenshot of output

echo "$(cal)"

_Su Mo Tu We Th Fr Sa  
                   1  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
30
_

echo $(cal)

_June 2019 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
_
1
jay-go

2つの重要な違いがあります。

  1. シェルは、引用符で囲まれていない$(cal)に対して単語分割を実行します。これは、IFSのデフォルト値を想定すると、空白のすべての文字列(改行を含む)が単一の空白に置き換えられることを意味します。これは、引用符で囲まれていないコマンドからの出力が1行になっていることです。

    より簡単な例を次に示します。

    _$ s='line     1
    > line  2'
    $ echo "$s"
    line     1
    line  2
    $ echo $s
    line 1 line 2
    _

    ご覧のとおり、二重引用符のない2番目のechoでは、空白のすべてのシーケンスが単一の空白に置き換えられています。これは、echo $(cal)で二重引用符なしでechoを使用したときに見たものです。

  2. シェルは、ワード分割の結果に対してパス名展開を実行します。これはあなたの例では何の違いもありませんが、出力に_?_または_*_または他のglob-active文字が含まれている場合、いくつかの驚きにつながる可能性があります。

    パス名展開の簡単な例を次に示します。 3つのファイルがあるディレクトリから始めましょう。

    _$ ls
    file1  file2  file3
    _

    それでは、文字列を定義しましょう:$ s = 'file?'

    ここで、二重引用符を使用したechoは文字列を返しますが、二重引用符を使用しない場合、文字列はファイル名に展開されます。

    _$ echo "$s"
    file?
    $ echo $s
    file1 file2 file3
    _
1
John1024