Як я можу розділити команду оболонки на кілька рядків при використанні оператора IF?


384

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

Це працює:

if ! fab --fabfile=.deploy/fabfile.py --forward-agent --disable-known-hosts deploy:$target; then rc=1                                                                       
fi

Це не працює:

# does not work:
if ! fab --fabfile=.deploy/fabfile.py \ 
  --forward-agent \
  --disable-known-hosts deploy:$target; then   
  rc=1
fi

Замість виконання всієї команди я отримую:

./script.sh: line 73: --forward-agent: command not found

Що ще важливіше, чого не вистачає в моєму розумінні Баша, що допоможе мені зрозуміти це та подібні проблеми в майбутньому?


2
Що таке помилка? Я можу виконати $ if ! cp -n log/server1.log \ > .; then echo no copy; fiбез помилок з новим рядком після\
— Мізерна змінна

15
У вас є пробіли після відкидання терміналу \ ? Їх досить важко помітити. Якщо це зробити, ви можете побачити, чи можете ви зробити редактор або видалити пробіли, або зробити їх більш видимими.
— msw

10
Так, це були пробіли після відхилення терміналу. Повністю. Дякую.
— Дмитро Міньковський

І так, вибачте, я повинен був розмістити "помилку" (несподіваний результат)! Моє ліжко! Редагування зараз.
— Дмитро Мінковський

Що ви розуміли? Це також не є частиною питання.
— хакре

Відповіді:


566

Продовження рядка не вдасться, якщо у вас є пробіл (пробіли або символи вкладки) після нахилу та перед новим рядком. Без такого пробілу, ваш приклад для мене працює добре:

$ cat test.sh
if ! fab --fabfile=.deploy/fabfile.py \
   --forward-agent \
   --disable-known-hosts deploy:$target; then
     echo failed
else
     echo succeeded
fi

$ alias fab=true; . ./test.sh
succeeded
$ alias fab=false; . ./test.sh
failed

Деякі деталі, викладені в коментарях: зворотний косий рядок продовження в оболонці насправді не є особливим випадком; це просто примірник загального правила, що зворотна косої риски "цитує" негайно наступного символу, запобігаючи будь-якому спеціальному лікуванню, яке воно, як правило, підлягає. У цьому випадку наступним символом є новий рядок, і спеціальне звернення, яке перешкоджає, - це припинення дії команди. Зазвичай цитований персонаж закінчується буквально включеним в команду; зворотний косий рядок замість цього видаляється повністю. Але в іншому випадку механізм той самий. А зворотна косої риски цитує лише наступного символу; якщо цей символ є пробілом або вкладкою, ви просто отримаєте процитований пробіл або вкладку, і будь-який наступний новий рядок залишається без котирування.


5
Марк, знаєте, у мене, мабуть, були пробіли. Я можу відтворити помилку лише під час додавання пробілів після `s. For example, when adding one after the first `, я отримую ./soundops: line 73: --forward-agent: command not found. Мої проблеми полягали в тому, що я не розумів цієї помилки. Чому наявність пробілу призводить до цієї помилки? Пробіл + \n"заперечує" `` і розмежовує команду?
— Дмитро Міньковський

83
Зворотний косий рядок перед новим рядком заважає новому рядку закінчувати команду. Але так само, як спеціальні послідовності евакуації, такі як "\ n", працюють лише з похилою косою рисою та n, ніколи між зворотною косою рисою та новою лінією нічого не працює.
— Марк Рід

18
Ха-ха-ха, звичайно, це має сенс. Ніколи так не бачив. Відкриття очей, але настільки просто: це просто вирваний новий рядок. Я ненавиджу невидимих ​​персонажів. Вони мали би для мене набагато більше сенсу, якби вони були просто видимими. Дякую!
— Дмитро Міньковський

7
У більшості редакторів можна зробити видимими ці невидимі символи.
— lucasvc

1
Зворотний косий рядок та новий рядок видаляються з ефективного командного рядка, але будь-який провідний пробіл у наступному рядку зберігається. Тож чи це проблема чи ні, залежить від того, чи буде пробіл проблемою в цей момент в однорядковій команді.
— Марк Рід

52

Для користувачів Windows / WSL / Cygwin тощо:

Переконайтесь, що ваші закінчення рядків є стандартними стрічками рядків Unix, тобто \n(LF).

Використання закінчень рядків Windows \r\n(CRLF) завершить розрив командного рядка.


Це відбувається тому, що наявність \у кінці рядка із закінченням рядка Windows означає переклад \ \r \n.
Як Марк правильно пояснює вище:

Продовження рядка не вдасться, якщо у вас є пробіл після зворотної косої риски та перед новою лінією.

Сюди входить не лише пробіл ( ) або вкладки ( \t), а й повернення каретки ( \r).


1
Це виправляє проблему, створену при створенні скрипту в Windows, а потім його використанні в Windows bash (наприклад, bash -c MyShellScript.sh, де MyShellScript.sh був створений в редакторі Windows). Вам потрібно зберегти MyShellScript.sh у форматі UNIX, можливо, використовуючи блокнот ++.
— BSalita
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.