1. ホーム
  2. bash

[解決済み] 変数を割り当てただけなのに、echo $variableには別のものが表示される。

2022-06-29 11:24:04

質問

以下は echo $var がちょうど割り当てられたものとは異なる値を表示することができます。これは、割り当てられた値が "double quoted" か 'single quoted' か unquoted かには関係なく起こります。

シェルに変数を正しく設定させるにはどうしたらよいですか。

アスタリスク

期待される出力は /* Foobar is free software */ ですが、代わりにファイル名のリストが出力されます。

$ var="/* Foobar is free software */"
$ echo $var 
/bin /boot /dev /etc /home /initrd.img /lib /lib64 /media /mnt /opt /proc ...

角括弧

期待値は [a-z] ですが、時々一文字で表示されることがあります。

$ var=[a-z]
$ echo $var
c

改行(ニューライン)

期待される値は、別々の行のリストですが、代わりにすべての値が1行にあります!

$ cat file
foo
bar
baz

$ var=$(cat file)
$ echo $var
foo bar baz

複数のスペース

私は慎重に整列されたテーブルのヘッダーを期待しましたが、代わりに複数のスペースが消えるか、1つに折りたたまれています!

$ var="       title     |    count"
$ echo $var
title | count

タブ

タブで区切られた2つの値を期待しましたが、代わりにスペースで区切られた2つの値が表示されます!

$ var=$'key\tvalue'
$ echo $var
key value

どのように解決するのですか?

上記のすべてのケースで、変数は正しく設定されていますが、正しく読み取られていません! 正しい方法は 二重引用符を使うことです。 を参照することです。 :

echo "$var"

これは、与えられたすべての例で期待される値を与えます。変数の参照は常に引用してください!


なぜですか?

ある変数が 非クォート であれば、そうなります。

  1. 以下を実行する フィールド分割 ここで、値は空白で複数の単語に分割されます(デフォルト)。

    以前は /* Foobar is free software */

    /* , Foobar , is , free , software , */

  2. これらの単語は、それぞれ パス名展開 が行われ、パターンがマッチするファイルに展開されます。

    以前は /*

    /bin , /boot , /dev , /etc , /home , ...

  3. 最後に、すべての引数はechoに渡され、echoはそれらを書き出します。 を半角スペースで区切って となり

    /bin /boot /dev /etc /home Foobar is free software Desktop/ Downloads/
    
    

    のように、変数の値の代わりに

変数が 引用 となります。

  1. その値に置き換えられます。
  2. ステップ2がない。

このため、あなたは 常にすべての変数参照を引用する であるべきなのです。特に単語分割やパス名展開を必要としない限り。このようなツールは シェルチェック のようなツールがあり、上記のすべてのケースで引用符の欠落について警告してくれます。