Дужки в умові: якщо я отримую синтаксичні помилки без пробілів?


17

Я використовую наведений нижче сценарій, щоб повернутись на два дні назад, коли сценарій працює з початку двох днів року, а також перевірити перший і другий дні кожного місяця і перемістити два дні назад.

if [$month="01"] && [$day="01"];
then
    date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
if [$month="01"] && [$day="02"];
then
         date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
   if [ $day = "01" ];
then
    date="$last_month/$yes_day/$year"
            fulldate="$year$last_month$yes_day"
else
        if [ $day = "02" ];
then
    date="$last_month/$yes_day/$year"
        fulldate="$year$last_month$yes_day"
else
    date="$month/$yes_day/$year"
        fulldate="$year$month$yes_day"
                fi
               fi
              fi
fi

Але я погано отримую повідомлення про помилку нижче

Etime_script.sh: line 19: [06=01]: command not found
Etime_script.sh: line 24: [06=01]: command not found

1
Наведені відповіді правильні; вам потрібен пробіл після [. Додатково загляньте у elifтвердження; це допоможе вам прибрати речі. Також крапки з комою після тверджень if якщо не потрібні, але також невірні, просто дивні.
Шон Дж. Гофф

@ ShawnJ.Goff Вони необхідні, якщо ви об'єднаєте наступний рядок ( if [ ... ]; then), тож не так незвично.
goldilocks

@goldilocks, так, це мій вподобаний стиль. Причина це незвично - це те, що він не робить цього.
Шон Дж. Гофф

Відповіді:


27

[не є ні метахарактером, ні керуючим оператором (навіть не зарезервоване слово; те саме для ]), тому він потребує пробілу навколо нього. В іншому випадку оболонка «бачить» команду [01=01]замість команди [з окремими параметрами 01, =, 01, і ]. Кожен оператор і операнд повинен бути окремим аргументом для [команди, тому пробіл необхідний і навколо операторів.

if [ "$month" = "01" ]

[$month="01"]це шаблон підстановки, який відповідає будь-якому з символів у $monthабо "01. Якщо це нічого не відповідає, воно залишається в спокої.

Якщо після закриття дужки є крапка з комою, то перед цим вам не знадобиться пробіл, оскільки крапка з комою завжди є частиною окремого маркера.

if [ "$month" = "01" ]; then

Те саме стосується синтаксису подвійних дужок bash (і ksh's і zsh's).

Більше однієї умови

Є два способи комбінування умов:

  1. всередині [

  2. з окремими [командами, поєднаними з &&або||

Групування з дужками, мабуть, простіше всередині [.

if [ "$month" = "01" -a "$day" = "01" ] # -a for and, -o for or

if [ "$month" = "01" ] && [ "$day" = "01" ]

Першого слід уникати, оскільки це ненадійно (спробуйте, наприклад, з month='!'). Проблем із дивним змінним вмістом можна уникнути, спочатку скориставшись безпечним рядком (якщо такий є); або за допомогою [[/ ]]замість [/ ]:

if [ "01" = "$month" -a "01" = "$day" ]

Як ми можемо співставити дві умови, якщо, наприклад, значення місяця == денне значення, якщо [$ month = "01"] && [$ day = "01"]; чекаю, що 01 && 01 вірно, тоді надрукуйте за умовами або перейдіть до іншої заяви
Kumar1

@AshokSanganahalli Я продовжив свою відповідь.
Hauke ​​Laging

1
[коли -a/ -oне використовуються, завжди надійно з оболонками, сумісними з POSIX. У використанні -a/-oнад цим немає жодної переваги &&/||. Я б напевно стримував його використання. Зауважте, що [[це не POSIX.
Стефан Шазелас

4

Ще один спосіб написати це:

case $month:$day in
  (01:0[12])
    date="$last_month/$yes_day/$last_year"
    fulldate="$last_month/$yes_day/$last_year"
    ;;
  (*:0[12])
    date="$last_month/$yes_day/$year"
    fulldate="$year$last_month$yes_day"
    ;;
  (*)
    date="$month/$yes_day/$year"
    fulldate="$year$month$yes_day"
esac

1
+1 для caseзаяви. Якщо у вас є більше elif, ви, ймовірно, використовуєте case.
HalosGhost

-1

Отже, це ваша відповідь:

if [ $var1 == $var2 ];
 then
    echo "bla bla"
fi

Отже, ви повинні покласти пробіл між квадратною дужкою та змінною / значенням.


ні, я не вгадаю, тому що, як я попросив скрипт перенести два дні назад, коли сценарій працює з початку двох днів року, а також перевірити перший і другий дні кожного місяця і перемістити два дні назад, це означає, якщо [$ month = "01"] && [$ day = "01"] ми припускаємо відповідати місяцю "01" та першому дню "01" істинним, переходимо до того або переходимо до іншого стану
Kumar1

1
@AshokSanganahalli: Я не знаю, як це пов’язано, але ваш стан IF не працює, оскільки у вас немає "порожнього простору" між квадратними дужками та значенням
Невен

@AshokSanganahalli Зазвичай, це не гарна ідея, щоб люди вашого рівня кваліфікації оскаржували виправлення людей, очевидно, краще розуміючи, хоча б не даючи підказки спробувати. Якби ваші здогадки були правильні, то вам не доведеться тут питати, чи не так?
Hauke ​​Laging

4
-1 для змін, що не котируються, та використання ==замість стандартних =.
Стефан Шазелас

2
Питання не позначене баш. Оператор порівняння рівності в стандартній команді [akatest є =. [якщо для тестів, він не виконує жодних завдань, тому не потрібно роз'єднуватись. Деякі [реалізації підтримують ==як розширення над стандартом, але не всі. Наприклад, оболонки Bourne, ash's, posh' [або /bin/[деякі системи. ==додав ksh, я вважаю, за узгодженість з тим самим оператором у його новій (( ... ))конструкції (яка має і =, і ==, але це не стандарт)
Stéphane Chazelas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.