シェルで変数の割り当てによってタブがスペースに置き換えられるのはなぜですか?
$ cat tmp
a b e c d
$ res=$(cat tmp)
$ echo $res
a b e c d
$res
空白を保持するには、変数を引用符で囲む必要があります。
$ cat file
a b e c d
$ res=$(cat file)
$ echo $res
a b e c d
$ echo "$res"
a b e c d
man bash
下からQUOTING
:
引用符は、特定の文字または単語の特別な意味をシェルから取り除くために使用されます。引用符を使用して、特殊文字の特別な処理を無効にしたり、予約語がそのように認識されないようにしたり、パラメーターの展開を防止したりできます。
上記の DEFINITIONS の下にリストされている各メタ文字は、シェルにとって特別な意味を持ち、それ自体を表す場合は引用符で囲む必要があります。
... \a alert (bell) \b backspace \e \E an escape character \f form feed \n new line \r carriage return \t horizontal tab \v vertical tab \\ backslash \' single quote \" double quote \nnn the eight-bit character whose value is the octal value nnn \xHH the eight-bit character whose value is the hexadecimal value HH \cx a control-x character ...
タブを失っているのは割り当てではなく、echo
コマンドを呼び出しています。
res
タブを含む値が割り当てられます。シェルで書くとき、それはその時点で変数$res
の内容を入力するのと同じです。res
そう:
$ echo $res
以下と同じです:
$ echo a b e c d
(その行の大きなスペースはタブ文字で、 を押して入力できますCtrl+V Tab
)。また、そのコマンドを実行すると、次の結果も得られます。
a b e c d
あなたの質問は実際には次のとおりです。コマンドの引数でタブが欠落するのはなぜですか?
答えは、コマンド (echo
この場合) がタブや実際にスペースを認識しないことです。シェルは、コマンドラインをコマンド名と引数のリストに解析します。空白 (タブとスペース) を使用して、コマンドをこれらの部分に分割します。次に、コマンドを実行し、引数リストを渡します。
したがってecho
、引数として受け取るのはリスト 'a'、'b'、'e'、'c'、'd' です。最初にどの文字がそれらを分離したかはわかりません。
次にecho
、各引数をスペースで区切って出力します。したがって、表示される出力。元のコマンド ラインでは、各引数を区切るために 1 つのスペース文字を使用していましたが、出力は入力と一致するため、入力のスペースが出力にも含まれているように見えますが、そうではありません。シェルは元のスペースを飲み込み、echo
いくつかの新しいものを挿入します。
引用符を使用して、シェルが複数の「単語」を単一の引数として扱うようにすることができます。たとえば、次のようにします。
$ echo a "b c" d
echo
これは 3 つの引数を'a'、'b c'、および 'd' に渡します。中間の引数には 4 つのスペースが含まれます。それらは に渡されるecho
ため、その出力に表示されます。引用符の外側のスペースは、引数を分割するためにシェルによって使用されるため、 には渡されませんecho
。したがって、出力は次のとおりです。
a b c d
この種のことを確認するには、受け取った引数の数とそれぞれの内容を正確に表示するコマンドを使用する方が明確です。この Perl ワンライナーはそれを行います:
$ perl -MData::Dumper -E 'say Dumper \@ARGV' a b c d
$VAR1 = [
'a',
'b',
'c',
'd'
];
$ perl -MData::Dumper -E 'say Dumper \@ARGV' "a b c d"
$VAR1 = [
'a b c d'
];
$ perl -MData::Dumper -E 'say Dumper \@ARGV' a "b c" d
$VAR1 = [
'a',
'b c',
'd'
];
$ res="a b c d"
$ perl -MData::Dumper -E 'say Dumper \@ARGV' $res
$VAR1 = [
'a',
'b',
'c',
'd'
];
$ perl -MData::Dumper -E 'say Dumper \@ARGV' "$res"
$VAR1 = [
'a b c d'
];