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.