Почему я должен заключить переменную в кавычки для если, но не для эха?

Вы забыли создавать свой initrd, который идет с ядром. Выполненный update-initramfs -c -k kernelversion и затем update-grub найти его и добавить его к меню личинки.

26
21.02.2013, 15:37
5 ответов

Вам всегда нужны кавычки вокруг переменных во всех контекстах списка, который является везде переменной, может быть расширен до нескольких значений, если Вы действительно не хотите 3 побочных эффектов отъезда закрывшей кавычки переменной.

контексты списка включают аргументы простым командам как [ или echo, for i in <here>, присвоения на массивы... Существуют другие контексты, где переменные также должны быть заключены в кавычки. Лучше всего должен всегда заключать переменные в кавычки, если у Вас нет очень серьезного основания не к.

Думайте об отсутствии кавычек (в контекстах списка) как split+glob оператор.

Как будто echo $test был echo glob(split("$test")).

Поведение оболочки сбивает с толку большинство людей, потому что на большинстве других языков, Вы помещаете кавычки вокруг фиксированных строк, как puts("foo"), а не вокруг переменных (как puts(var)) в то время как в оболочке это наоборот: все - строка в оболочке, так помещение кавычек вокруг всего было бы громоздким, Вы echo test, Вы не должны "echo" "test". В оболочке кавычки используются для чего-то еще: предотвратите некоторое особое значение некоторых символов и/или влияйте на поведение некоторых расширений.

В [ -n $test ] или echo $test, оболочка разделит $test (на пробелах по умолчанию), и затем работают, поколение имени файла (расширьтесь весь *, '?'... шаблоны к списку соответствия регистрируют), и затем передайте тот список аргументов [ или echo команды.

Снова, думайте о нем как "[" "-n" glob(split("$test")) "]". Если $test пусто или содержит только пробелы (SPC, вкладка, nl), затем split+glob оператор возвратит пустой список, таким образом, [ -n $test ] будет "[" "-n" "]", который является тестом, чтобы проверить, является ли "-n" пустой строкой или нет. Но вообразите то, что произошло бы если $test был "*" или "= нечто"...

В [ -n "$test" ], [ передается эти четыре аргумента "[", "-n", "" и "]" (без кавычек), который является тем, что мы хотим.

Является ли это echo или [ не имеет никакого значения, это - просто это echo производит то же самое, передало ли оно пустой аргумент или никакой аргумент вообще.

См. также этот ответ на подобный вопрос для получения дополнительной информации о [ команда и [[...]] создать.

36
27.01.2020, 19:40

Ответ @h3rrmiller хорош для объяснения, почему Вам нужны кавычки для if (или скорее [/test), но я на самом деле установил бы тот Ваш вопрос, является неправильным.

Попробуйте следующие команды, и Вы будете видеть то, что я имею в виду.

export testvar="123    456"
echo $testvar
echo "$testvar"

Без кавычек подстановка переменных заставляет вторую команду расширяться до:

echo 123    456

и несколько пробелов сворачиваются к единственному:

echo 123 456

С кавычками сохраняются пробелы.

Это происходит потому что при заключении в кавычки параметра (передается ли тот параметр echo, test или некоторая другая команда), значение того параметра отправляется как одно значение в команду. Если Вы не заключаете его в кавычки, оболочка делает свое нормальное волшебство поиска пробела для определения, где каждый параметр запускается и заканчивается.

Это может также быть проиллюстрировано следующей (очень очень простой) программой C. Попробуйте следование командной строки (можно хотеть сделать это в пустом каталоге чтобы к не риску перезаписать что-то).

cat <<EOF >paramtest.c
#include <stdio.h>
int main(int argc, char **argv) {
  int nparams = argc-1; /* because 1 parameter means only the executable's name */
  printf("%d parameters received\n", nparams);
  return nparams;
}
EOF
cc -o paramtest paramtest.c

и затем...

./paramtest 123 456
./paramtest "123 456"
./paramtest 123   456
./paramtest "123   456"

После выполнения paramtest, $? будет содержать количество параметров, оно было передано (и то число будет распечатано).

7
27.01.2020, 19:40

Без кавычек $test мог расшириться, чтобы быть больше чем одним словом, таким образом, оно должно быть заключено в кавычки для не повреждения синтаксиса начиная с каждого переключателя в [ команда ожидает один аргумент, который является тем, что кавычки делают (делает что $test расширяется до в один аргумент),

Причина Вам не нужны кавычки для расширения переменной с echo то, потому что это не ожидает один аргумент. Это просто распечатает то, чему Вы говорите это. Итак, даже если $test расширяется до 100 эха слов, все еще распечатает его.

Смотрите на Ловушки Bash

0
27.01.2020, 19:40
  • 1
    да, но почему нам не нужен он для echo? –  CharlesB 21.02.2013, 15:51
  • 2
    @CharlesB Вам действительно нужны кавычки для echo. Что заставляет Вас думать иначе? –  Gilles 'SO- stop being evil' 21.02.2013, 23:37
  • 3
    мне не нужны они, я могу echo $test и это работает (это производит значение $test) –  CharlesB 22.02.2013, 00:05
  • 4
    @CharlesB Это только производит значение $test, если это не содержит несколько пробелов нигде. Попробуйте программу в моем ответе для иллюстрации причины. –  a CVn 22.02.2013, 11:17

Это - все о том, как оболочка интерпретирует строку, прежде чем программа будет выполнена.

Если строка читает echo I am $USER, оболочка разворачивает его до echo I am blrfl и echo не имеет никакой подсказки, является ли источник текста литералом или переменным расширением. Точно так же, если строка читает echo I am $UNDEFINED, оболочка расширится $UNDEFINED ни во что и аргументы эха будет I am, и это - конец его. С тех пор echo работает просто великолепно без аргументов, echo $UNDEFINED абсолютно допустимо.

Ваша проблема с if не действительно с if, потому что if просто запускает любую программу, и аргументы следуют за нею, и выполняется then часть, если программа выходит 0 (или else часть, если существует один и выходы программы не -0):

if /bin/true ; then echo True dat. ; fi
if fgrep -q blrfl /etc/passwd ; then echo Blrfl has an account. ; fi

Когда Вы используете if [ ... ] чтобы сделать сравнение, Вы не используете примитивы, встроенные в оболочку. Вы на самом деле даете оболочке команду запускать названную программу [ который является очень небольшим надмножеством test(1) это требует, чтобы его последний аргумент был ]. Оба выхода программ 0 если условие испытания вышло верное и 1 если это не сделало.

Причина, которую повреждают некоторые тесты, когда переменная является неопределенной, состоит в том потому что test не видит, что Вы используете переменную.Следовательно, [ $UNDEFINED -eq 2 ] повреждения, потому что к тому времени, когда оболочка сделана с ним, все test видит аргументы, -eq 2 ], который не является допустимым тестом. Если Вы сделали это с чем-то определенным, такой как [ $DEFINED -ne 0 ], это работало бы, потому что оболочка развернет его в допустимый тест (например, 0 -ne 0).

Существует семантическое различие между foo $UNDEFINED bar, который расширяется до двух аргументов (foo и bar) потому что $UNDEFINED соответствовавший его имя. Сравните это с foo "$UNDEFINED" bar, который расширяется до трех аргументов (foo, пустая строка и 'панель). Кавычки вынуждают оболочку интерпретировать их как аргумент, существует ли что-нибудь между ними или нет.

2
27.01.2020, 19:40

Пустые параметры удалены если не заключенный в кавычки:

start cmd:> strace -e trace=execve echo foo $bar baz
execve("/usr/bin/echo", ["echo", "foo", "baz"], [/* 100 vars */]) = 0

start cmd:> strace -e trace=execve echo foo "$bar" baz
execve("/usr/bin/echo", ["echo", "foo", "", "baz"], [/* 100 vars */]) = 0

Названная команда не видит, что был пустой параметр на командной строке оболочки. Кажется, что [определяется для возврата 0 для-n ни с чем после. Whyever.

Заключение в кавычки действительно имеет значение для эха также в нескольких случаях:

var='*'
echo $var
echo "$var"

var="foo        bar"
echo $var
echo "$var"
0
27.01.2020, 19:40
  • 1
    Это не echo, это - оболочка. Вы видели бы то же поведение с ls. Попробовать touch '*' некоторое время, если Вы чувствуете себя предприимчивыми. :) –  a CVn 21.02.2013, 16:18
  • 2
    Это просто формулирует, поскольку нет никакого различия к 'если [...]' случай. [не специальная команда оболочки. Это отличается от [[(в ударе), где заключение в кавычки не необходимо. –  Hauke Laging 21.02.2013, 17:06

Теги

Похожие вопросы