Почему переменная назначения заменяет вкладки пробелами в оболочке?
$ cat tmp
a b e c d
$ res=$(cat tmp)
$ echo $res
a b e c d
Почему переменная назначения заменяет вкладки пробелами в оболочке?
$ 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
:
Quoting используется для удаления специального значения определенных символов или слов в оболочке. Цитирование может использоваться для отключения специальной обработки для специальных символов, для предотвращения сохранения зарезервированных слов как таковых и предотвращения расширения параметров.
Каждый из метасимволов, перечисленных выше в разделе ОПРЕДЕЛЕНИЯ, имеет особое значение для оболочки и должен быть указан, если он должен представлять себя.
... \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
then делает, выводит каждый из его аргументов, пробел между ними. Отсюда вывод, который вы видите. Если исходная командная строка использовала одиночный пробел для разделения каждого аргумента, вывод соответствует входу, поэтому он выглядит скорее так же, как и пробелы на входе, но они не являются: оболочка собирает исходные пространства и echo
вставляет некоторые новые.
Маркеры комментариев могут использоваться, чтобы заставить оболочку рассматривать несколько слов как один аргумент. Например, если вы выполните:
$ echo a "b c" d
который передает 3 аргумента для echo
: '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'
];