У меня есть сценарий оболочки с именем «teleport.sh», как это:
if [ $1="1" ];
then
shift
mv "$@" ~/lab/Sun
elif [ $1="2" ];
then
shift
mv "$@" ~/lab/Moon
elif [ $1="3" ];
then
shift
mv "$@" ~/lab/Earth
fi
Когда я выполню:
sh teleport.sh 2 testfile
Это testfile
перемещено в ~/lab/Sun
каталог, что меня очень смущает, так как я не передал 1 или '1' в этот скрипт.
Что здесь не так?
$var
,$(cmd)
и даже`cmd`
[которым$(cmd)
следует отдавать предпочтение]). Есть некоторые крайние случаи, когда вам не нужно цитировать, но всегда делать это не повредит.$(cmd)
это команда подстановки , ( в основном) такой же , как`cmd`
. См. Mywiki.wooledge.org/CommandSubstitution и mywiki.wooledge.org/BashFAQ/082Ответы:
Использование пробелов решает вашу проблему.
Хотя это аккуратнее
источник
$1="1"
синтаксис "работает" вообще (дает истинный результат). Как[
/test
встроенная на самом деле интерпретирует это выражение?test
видит только один аргумент («l-значение»). Без других аргументов («оператор» и «r-значение») проверять нечего, поэтомуtest
просто говорит: «Хорошо, да, вы дали мне кое-что, и это должно быть бессмысленно верно».$1="1"
это$1
сцепляются по=1
Во- первых очевидно , что это вы должны обеспечить пробелы между аргументами
[
,test
или[[
:В Bash
[[ ]]
рекомендуется использовать, так как он не делает ненужных вещей для условного выражения, таких как разбиение слов и расширение пути. Цитировать вокруг двойных кавычек тоже не нужно. Также==
может быть использован более читаемый оператор .Добавлено примечание: Если второй операнд также содержит переменные, цитирует необходимо , так как это может быть при условии сопоставления с образцом , если он содержит узнаваемые символы , такие как
*
,?
,[]
и т.д .. Если расширенная подстановки или соответствующий шаблон включенshopt -s extglob
, другие формы , как@()
,!()
и т.д. также будет распознаваться как шаблоны. Смотрите Pattern Matching .С такими операторами, как
<
и>
это, все еще может быть необходимо, поскольку я однажды столкнулся с ошибкой, при которой не цитирование второго аргумента приводило к другим результатам.Что касается первого операнда, ничего не применяется.
Рассмотрим и этот более простой вариант:
Или сжатый:
"${@:2}"
является формой расширения подстроки или расширения элемента массива, где2
это смещение. Это заставляет расширение начинаться со второго значения. С этим нам, возможно, не понадобится пользоватьсяshift
.Добавленное
--
предотвращаетmv
распознавание имен файлов, начинающихся с dash (-
), как недопустимых параметров.источник
;&
вместо;;
(только ksh, bash, zsh). Но тогдаbreak
все равно не препятствует провалу,break
остается только вырваться из петель.if
а[
команда.[[ $foo == $bar ]]
будет выполнять сопоставление с образцом, но[[ $foo == "$bar" ]]
не будет.Для того, чтобы ответить на вопрос о том, почему это происходит, такое поведение
[
иначеtest
как описано в стандарте POSIX :Вы передаете ему 1 аргумент,
2=1
который не является нулевым, и поэтомуtest
завершается с успехом.Как указывают другие сообщения (и проверка оболочки ), если вы хотите сравнить на равенство, вам вместо этого нужно будет передать 3 аргумента
2
,=
и1
.источник
Я просто хочу порекомендовать портативную, но также более аккуратную альтернативу. Bash не универсален (и если вам не нужен универсальный, зачем вы пишете скрипт оболочки?)
(Примечание для педантов: да, я знаю, что в кавычках
$action
наcase "$action" in
строчке нет необходимости, но я чувствую, что в любом случае лучше поместить их туда, чтобы будущие читатели не должны были это помнить.)источник
/bin/sh
сценарии, если вам это нужно; в противном случае, пишите на языке сценариев, который менее ужасен, чем shell. Базовый интерпретатор Perl на самом деле более вероятно присутствует в устаревших проприетарных средах и урезанных встроенных средах, чем Bash.