Jak mogę podzielić polecenie powłoki na wiele wierszy, używając instrukcji JEŻELI?


384

Jak mogę podzielić polecenie na wiele wierszy w powłoce, gdy polecenie jest częścią ifinstrukcji?

To działa:

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

To nie działa:

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

Zamiast wykonania całego polecenia otrzymuję:

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

Co ważniejsze, czego brakuje w moim rozumieniu Bash, które pomogą mi zrozumieć tę i podobne problemy w przyszłości?


2
Jaki jest błąd? Jestem w stanie wykonać $ if ! cp -n log/server1.log \ > .; then echo no copy; fibez błędu, z nowym wierszem po\
Nędzna zmienna

15
Czy masz spacje po odwróceniu zacisków terminala \ ? Trudno je zobaczyć. Jeśli tak, możesz sprawdzić, czy możesz zmusić edytora do usunięcia końcowych spacji lub zwiększenia ich widoczności.
msw

10
Tak, to były spacje po odwróceniu zacisków terminala. Całkowicie. Dziękuję Ci.
Dmitry Minkovsky,

I tak, przepraszam, powinienem był opublikować „błąd” (nieoczekiwany wynik)! Mój błąd! Edycja teraz.
Dmitry Minkovsky,

Jakie było twoje zrozumienie? To też nie jest część pytania.
hakre

Odpowiedzi:


566

Kontynuacja linii nie powiedzie się, jeśli po odwrotnym ukośniku i przed nową linią występują białe spacje (spacje lub znaki tabulacji). Bez takich białych znaków twój przykład działa dla mnie dobrze:

$ 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

Niektóre szczegóły promowane z komentarzy: odwrotny ukośnik kontynuacji linii w powłoce nie jest tak naprawdę szczególnym przypadkiem; jest to po prostu przykład ogólnej zasady, że ukośnik odwrotny „cytuje” bezpośrednio następujący po nim znak, zapobiegając jakiemukolwiek specjalnemu traktowaniu, któremu normalnie by się poddał. W tym przypadku następnym znakiem jest nowa linia, a specjalnym zapobieganiem jest zakończenie polecenia. Zazwyczaj cytowany znak pojawia się dosłownie w poleceniu; znak nowej linii z odwrotnym ukośnikiem jest zamiast tego całkowicie usuwany. Ale poza tym mechanizm jest taki sam. Odwrotny ukośnik cytuje tylko bezpośrednio następujący znak; jeśli ten znak jest spacją lub tabulatorem, otrzymasz po prostu cytowaną spację lub tabulator, a każda kolejna nowa linia pozostanie bez cudzysłowu.


5
Mark, wiesz, musiałem mieć białe spacje. Jestem w stanie odtworzyć błąd tylko po dodaniu białych znaków po `s. For example, when adding one after the first `, rozumiem ./soundops: line 73: --forward-agent: command not found. Moje problemy polegały na tym, że nie zrozumiałem tego błędu. Dlaczego spacja powoduje ten błąd? Biała spacja + \n„neguje” znak „i ogranicza polecenie?
Dmitry Minkovsky,

83
Odwrotny ukośnik przed znakiem nowej linii uniemożliwia nowej linii zakończenie polecenia. Ale podobnie jak specjalne sekwencje specjalne, takie jak „\ n”, działają tylko z niczym między odwrotnym ukośnikiem a n, tak i odwrotny ukośnik działa tylko z niczym między odwrotnym ukośnikiem a nowym wierszem.
Mark Reed,

18
Hahaha wow, oczywiście to ma sens. Nigdy tego tak nie widziałem. Otwierające oczy, ale takie proste: to tylko uciekająca nowa linia. Nienawidzę niewidzialnych postaci. Gdyby wszyscy byli tylko widoczni, mieliby dla mnie o wiele większy sens. Dziękuję Ci!
Dmitry Minkovsky,

7
W większości edytorów możesz uwidocznić te niewidzialne znaki.
lucasvc

1
Ukośnik odwrotny i znak nowej linii są usuwane z efektywnego wiersza polecenia, ale zachowane są wszystkie wiodące białe znaki w następnym wierszu. Tak więc, czy jest to problem, czy nie, zależy od tego, czy białe znaki będą w tym momencie problemem w poleceniu jednowierszowym.
Mark Reed,

52

Dla użytkowników Windows / WSL / Cygwin itp .:

Upewnij się, że zakończenia linii są standardowymi uniksowymi liniami, tj \n. Tylko (LF).

Korzystanie z zakończeń linii systemu Windows \r\n(CRLF) spowoduje przerwanie podziału wiersza poleceń.


Wynika to z faktu, że posiadanie \na końcu linii z zakończeniem linii Windows przekłada się na \ \r \n.
Jak Mark poprawnie wyjaśnia powyżej:

Kontynuacja linii nie powiedzie się, jeśli masz spacje po odwrotnym ukośniku i przed nową linią.

Dotyczy to nie tylko spacji ( ) lub tabulatorów ( \t), ale także znaku powrotu karetki ( \r).


1
Rozwiązuje to problem powstały podczas tworzenia skryptu w systemie Windows, a następnie używania go w systemie Windows bash (np. Bash -c MyShellScript.sh, gdzie MyShellScript.sh został utworzony w edytorze Windows). Musisz zapisać MyShellScript.sh w formacie UNIX, być może używając notatnika ++.
BSalita,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.