为什么变量赋值会在shell中用空格替换制表符?
$ cat tmp
a b e c d
$ res=$(cat tmp)
$ echo $res
a b e c d
答案 0 :(得分:14)
您需要引用变量$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
:
引用用于删除某些字符的特殊含义 或者是shell的话。 引用可用于禁用特殊字符的特殊处理,以防止 保留字不被识别,并防止参数扩展。
上面列出的每个元字符对于shell都有特殊含义 如果要代表自己,必须引用它。
... \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 ...
答案 1 :(得分:7)
失去标签但不是调用echo
命令的赋值不是。
res
分配了一个包含标签的值。当你在shell中编写$res
时,这相当于在那时输入res
变量的内容。
所以:
$ echo $res
与:
相同$ echo a b e c d
(该行中的大空格是制表符,可以通过按Ctrl+V Tab
键入)。如果你运行该命令,你也会得到:
a b e c d
所以你的问题实际上是:为什么在命令的参数中缺少标签?
答案是命令(在这种情况下为echo
)永远不会看到标签,或者确实是空格。 shell将您的命令行解析为命令名和参数列表。它使用空格(制表符和空格)将命令拆分为这些部分。然后它运行命令,并将参数列表传递给它。
那么echo
作为参数接收的是列表'a','b','e','c','d';它不知道哪些角色最初将它们分开。
然后echo
输出每个参数,并在它们之间留一个空格。因此你看到的输出。在原始命令行使用单个空格字符分隔每个参数的情况下,输出与输入匹配,因此它看起来很像输入中的空格也在输出中 - 但它们不是:shell吞噬原始空间和echo
会插入一些新内容。
引号可用于使shell将多个“单词”视为单个参数。例如,如果你这样做:
$ echo a "b c" d
将3个参数传递给echo
:'a','b c'和'd'。中间参数包含4个空格;那些传递给echo
,因此会出现在它的输出中。引号外部的空格由shell用于分割参数,因此不会传递给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'
];