2010-08-24 2 views
0
while [ $done = 0 ] 
    do 
    echo -n "Would you like to create one? [y/n]: " 
    read answer 
    if [ "$(answer)" == "y" ] || [ "$(answer)" == "Y" ]; then 
    mkdir ./fsm_$newVersion/trace 
    echo "Created trace folder in build $newVersion" 
    $done=1 
    elif [ "$(answer)" == "n" ] || [ "$(answer)" == "N" ]; then 
    $done=2 
    else 
    echo "Not a valid answer" 
    fi 
done 

Хорошо, поэтому у меня есть этот простой bashscript, который просто пытается получить вход от пользователя и проверить его. Однако я получаю эту ошибкуBASH: чтение во время цикла

./test.sh: line 1: answer: command not found 
./test.sh: line 1: answer: command not found 
./test.sh: line 1: answer: command not found 
./test.sh: line 1: answer: command not found 

Что я понятия не имею, почему, потому что «ответ» нигде вблизи линии 1. Так я столкнулся с этой article

Который имеет смысл, так как он имеет в виду линию 1 и может Не находите ответа. Поэтому, похоже, начинается новая подоболочка. Однако я действительно не понял решения и не могу понять, как я применил бы его к моему делу. Я просто хочу, чтобы это сработало.

ответ

7

$(answer) не подставляет значение переменной answer. Он выполняет команду answer в качестве команды и заменяет вывод этой команды. Вы хотите ${answer} везде, где есть $(answer). В этом случае вы можете уйти с голыми $answer тоже, но чрезмерное использование ${...} - хорошая паранойя.

(?. Вы, возможно, используется для написания Makefiles $(...) и ${...} одинаковы в Makefiles, но оболочка отличается)

Кстати, у вас есть какие-то другие ошибки:

  • В shell, вы не ставите знак доллара на имя переменной в левой части задания. Вам необходимо изменить $done=1 на done=1 и аналогичным образом для $done=2.
  • Вы не достаточно параноичны относительно своих переменных замещений. Если вы не знаете по факту, что он делает неправильную вещь в каком-то конкретном случае, вы должны всегда wrap все переменные замены в двойных кавычках. Это влияет как на команду mkdir, так и на состояние цикла while.
  • Вы не достаточно параноичны относительно аргументов test (aka [). Вам необходимо прикрепить обе стороны теста равенства x, чтобы они не могли быть неверно истолкованы как переключатели.
  • == не является переносной оболочкой, вместо этого используется = (нет разницы в bash, но многие оболочки без bash не поддерживают == вообще).

Положите все это вместе, и это то, что ваш скрипт должен выглядеть следующим образом:

while [ "x${done}" = x0 ]; do 
    echo -n "Would you like to create one? [y/n]: " 
    read answer 
    if [ "x${answer}" = xy ] || [ "x${answer}" = xY ]; then 
    mkdir "./fsm_${newVersion}/trace" 
    echo "Created trace folder in build $newVersion" 
    done=1 
    elif [ "x${answer}" = xn ] || [ "x${answer}" = xN ]; then 
    done=2 
    else 
    echo "Not a valid answer" 
    fi 
done 
+0

Ahh спасибо! Я боролся с этим в течение часа. Это первый случай, когда я попытался написать сценарий bash (или любой скрипт). – Albinoswordfish

+0

Рад помочь. Я немного расширил ответ, у вас были другие ошибки. – zwol

+0

О, также, причина, по которой он говорит «строка 1», заключается в том, что «ответ» находится в строке 1 * вложенного сценария оболочки, вызванного '$ (...)' *. Да, это менее полезно, на самом деле, возможно, ошибка в оболочке. – zwol

0

Which I have no idea why because "answer" is nowhere near line 1. So I ran into this article

Это не ваша проблема.

Я запустил сценарий и не получил полученную вами ошибку. Я получил ошибку:

./test.sh: line 1: [: -eq: unary operator expected 

, когда я попытался скомпилировать. Определение сделано исправлено. Следующий сценарий должен работать ...

#!/bin/bash 

done=0 
while [ $done -eq 0 ] 
do 
    echo -n "Would you like to create one? [y/n]: " 
    read answer 
    if [[ "$(answer)" == "y" || "$(answer)" == "Y" ]]; then 
    mkdir ./fsm_${newVersion}/trace 
    echo "Created trace folder in build $newVersion" 
    $done=1 
    elif [[ "$(answer)" == "n" || "$(answer)" == "N" ]]; then 
    $done=2 
    else 
    echo "Not a valid answer" 
    fi 
done 

...обратите внимание, что вы выполняли строковые сравнения по вашей переменной, которую вы, по-видимому, считали числовой. Обычно это плохая форма для сравнения строк в переменной числового типа, хотя она будет работать. Вместо этого используйте -eq (оператор арифметического сравнения). (Также обратите внимание, что если вы сохранили этот тест, ваше равенство строк было бы непоследовательным ... у вас было «=» в одном месте и «==» в другом месте ... nitpicking здесь, но полезно быть последовательным).

Кроме того, я предлагаю двойные скобки для ваших сложных условных чисел, так как они будут более читабельными, если у вас есть более длинные. например

if [[($var1 -eq 0 && $var2 -eq 1) || ($var1 -eq 1 && $var2 -eq 0)]]; then 

Как раз то, что у вас есть только два условия, но может быть полезно в будущем.

Также вам не хватало скобки '{' '}' вокруг вашей переменной newVersion.

Наконец, я предлагаю положить строку #!/Bin/bash в верхней части вашего скрипта. В противном случае это зависит от вашей среды, чтобы определить, что делать с вашим скриптом, что является плохим.

+0

К сожалению, тесты с двойными скобками гораздо менее переносимы, чем тесты с одним кронштейном, которые работают повсюду, пока вы знаете все маленькие трюки (например, префиксы x и не используете -a/-o). – zwol

+0

Возможно, но я думаю, что они гораздо более читабельны, и я не сталкивался с какими-либо крупными дистрибутивами, которые они не работали до сих пор, что я помню (использовались Red Hat, CentOS, Ubuntu и Fedora ...) –

+0

Вы действительно не сталкиваетесь с серьезными проблемами, связанными с переносимостью оболочки, если вы ограничиваете себя Linux. Poke at OpenSolaris без каких-либо установленных инструментов GNU и без '/ usr/xpg4/bin' в вашем $ PATH, некоторое время. (И тогда, если ваше здравомыслие сохранится, найдите себе учетную запись AIX.) – zwol

Смежные вопросы