например.
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
и используя escape-символ "\":
me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR
Я, очевидно, делаю что-то глупое.
Как получить выход "BAR * BAR"?
например.
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
и используя escape-символ "\":
me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR
Я, очевидно, делаю что-то глупое.
Как получить выход "BAR * BAR"?
Цитата при установке $FOO недостаточно. Вы также должны указать ссылку на переменную:
me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR
SHORT ANSWER
Как и другие, вы всегда должны указывать переменные, чтобы предотвратить странное поведение. Поэтому вместо echo $foo используйте echo "$ foo".
ДОЛГОЙ ОТВЕТ
Я думаю, что этот пример требует дальнейшего объяснения, потому что происходит больше, чем может показаться на первый взгляд.
Я вижу, где возникает ваше замешательство, потому что, после того как вы запустили свой первый пример, вы, вероятно, подумали, что оболочка явно делает:
Итак, из вашего первого примера:
me$ FOO="BAR * BAR"
me$ echo $FOO
После расширения параметра эквивалентно:
me$ echo BAR * BAR
И после расширения имени файла эквивалентно:
me$ echo BAR file1 file2 file3 file4 BAR
И если вы просто наберете echo BAR * BAR
в командной строке, вы увидите, что они эквивалентны.
Итак, вы, вероятно, подумали о себе: "если я уйду из *, я могу предотвратить расширение имени файла"
Итак, из вашего второго примера:
me$ FOO="BAR \* BAR"
me$ echo $FOO
После расширения параметра должно быть эквивалентно:
me$ echo BAR \* BAR
И после расширения имени файла должно быть эквивалентно:
me$ echo BAR \* BAR
И если вы попытаетесь ввести "echo BAR\* BAR" непосредственно в командной строке, он действительно напечатает "BAR * BAR", потому что расширение файла предотвращается побегом.
Так почему же использование $foo не работает?
Это потому, что есть третье расширение, которое имеет место - Снятие цитаты. Из bash удаления цитаты вручную:
После предыдущих расширений все неупорядоченные вхождения символов '\,' 'И' ', что не привело из одного из указанных выше расширений удалены.
Итак, что происходит, когда вы вводите команду непосредственно в командную строку, escape-символ не является результатом предыдущего расширения, поэтому bash удаляет его перед отправкой в команду echo, но во втором примере "\ *" был результатом предыдущего расширения параметра, поэтому он НЕ удаляется. В результате эхо получает "\ *" и то, что он печатает.
Обратите внимание, что разница между первым примером - "*" не включена в символы, которые будут удалены с помощью удаления цитаты.
Надеюсь, это имеет смысл. В заключение вывод в том же - просто используйте цитаты. Я просто подумал, что я объясню, почему ускользает, что логически должно работать, если играется только параметр и имя файла, не работает.
Для полного объяснения разложений bash см.:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
Я немного добавлю этот старый поток.
Обычно вы используете
$ echo "$FOO"
Однако у меня были проблемы даже с этим синтаксисом. Рассмотрим следующее script.
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
*
необходимо передать дословно curl
, но будут возникать те же проблемы. Вышеприведенный пример не будет работать (он будет расширяться до имен файлов в текущем каталоге), и не будет \*
. Вы также не можете процитировать $curl_opts
, потому что он будет признан одним (недопустимым) параметром curl
.
curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
Поэтому я бы рекомендовал использовать переменную bash
$GLOBIGNORE
, чтобы предотвратить расширение имени файла вообще при применении к глобальному шаблону или использовать встроенный флаг set -f
.
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
Применение к исходному примеру:
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
me$ set -f
me$ echo $FOO
BAR * BAR
me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR
FOO='BAR * BAR'
echo "$FOO"
echo "$FOO"
Возможно, стоит привыкнуть использовать printf
, а не echo
в командной строке.
В этом примере это не приносит большой пользы, но может быть более полезным при более сложном выходе.
FOO="BAR * BAR"
printf %s "$FOO"