Składnia wielowierszowa do potokowania heredoc; czy to jest przenośne?


137

Jestem zaznajomiony z tą składnią:

cmd1 << EOF | cmd2
text
EOF

ale właśnie odkryłem, że bash pozwala mi pisać:

cmd1 << EOF |
text
EOF
cmd2

(heredoc jest używany jako dane wejściowe do cmd1, a wyjście cmd1 jest przesyłane potokiem do cmd2). Wydaje się, że jest to bardzo dziwna składnia. Czy jest przenośny?


Przyszedłem tutaj, aby znaleźć dobrego sposobu podziału tego na wielu liniach: big-long-command1 with lots of args << EOF | big-long-command2 with lots of args. „Dziwna składnia” wydaje się najlepszym sposobem.
— PaulC

Jednym z wygodnych przypadków użycia jest sytuacja, gdy próbujesz przekonwertować tabelę rozdzieloną spacjami na tabelę rozdzielaną tabulatorami, aby można ją było wkleić do Arkuszy kalkulacyjnych Google. Nie będziesz musiał tworzyć pliku tymczasowego.
— Sridhar Sarnobat,

Pierwszy nie działał dla mnie w powłoce z. Nie podoba mi się ten drugi, ponieważ zraża | z polecenia, tracąc idiomację (?) rurociągów powłokowych.
— Sridhar Sarnobat

Odpowiedzi:


109

Tak, standard POSIX na to pozwala. Według wersji z 2008 roku:

Dokument tutaj będzie traktowany jako pojedyncze słowo, które zaczyna się po następnym <newline>i trwa do momentu, gdy pojawi się wiersz zawierający tylko separator i a <newline>, bez <blank>znaków między nimi. Następnie rozpoczyna się następny dokument tutaj, jeśli taki istnieje.

I zawiera ten przykład wielu „dokumentów tutaj” w jednym wierszu:

cat <<eof1; cat <<eof2
Hi,
eof1
Helene.
eof2

Nie ma więc problemu z przekierowaniami lub potokami. Twój przykład jest podobny do tego:

cat file |
cmd

A gramatyka powłoki (dalej na połączonej stronie) zawiera następujące definicje:

pipe_sequence    :                             command
                 | pipe_sequence '|' linebreak command

newline_list     :              NEWLINE
                 | newline_list NEWLINE
                 ;
linebreak        : newline_list
                 | /* empty */

Tak więc po symbolu rury może następować koniec linii i nadal może być uważany za część rurociągu.


26

Tak, jest w gramatyce powłoki POSIX. Możesz także mieć więcej niż jeden dokument here-doc dla tego samego polecenia (niektóre inne przykłady używają dwóch catwywołań, ale to również działa):

cat <<EOF1 <<EOF2
first here-doc
EOF1
second here-doc
EOF2

Jest to wymyślone (używając 2 here-docs dla stdin), ale jeśli myślisz o wprowadzeniu danych wejściowych dla różnych deskryptorów plików, od razu ma to sens.

Istnieje również możliwość całkowitego usunięciacat . Dlaczego nie udostępnić tego dokumentu bezpośrednio dla cmd:

cmd << EOF
input
here
EOF

`` `` cat << EOF1 << EOF2 pierwszy tutaj-doc EOF1 drugi tutaj-doc EOF2 '' `` Powyższe nie działa.
— user1424739

@ user1424739 Działa w aktualnym zsh i bash. Ash i ksh93 wydają się wyświetlać tylko drugi dokument.
— Jens

Dlaczego głos przeciw? Jeśli jest coś niedokładnego, daj mi szansę, aby to naprawić.
— Jens

To jest całkiem słodkie podczas używania sudo tee /etc/securefile.conf <<EOF.
— dragon788

Na jakiej wersji bash to działa? Używając basha 4.4.19 (na ubuntu 18.04.02) i bash 5.0 (obraz dockera), dostałem tylko drugi tutaj-doc. A może jest jakaś konkretna opcja?
— huelbois

18

Hmm, chyba tak, zgodnie z testem w bash w trybie POSIX:

$ bash --posix
$ cat <<EOF |
> ahoj
> nazdar
> EOF
> sed 's/a/b/'
bhoj
nbzdar

Jeszcze jedna drobna uwaga: nie umieszczaj spacji po zamknięciu EOF. Monit zachowa się dziwnie i będziesz się zastanawiać, co do cholery jest nie tak
— Sridhar Sarnobat

2
Uruchomienie basha w trybie POSIX wyłącza niektóre rozszerzenia, ale w żadnym wypadku nawet prawie wszystkie z nich. W związku z tym, chociaż ta odpowiedź jest poprawna pod względem tego, na co pozwala POSIX, jej rozumowanie nie wspiera tego zbyt skutecznie.
— Charles Duffy,

3

Cześć, sprawdź to na przykład

#!/bin/sh
( base32 -d | base64 -d )<<ENDOFTEXT
KNDWW42DNNSHS5ZXPJCG4MSVM5MVQVT2JFCTK3DELBFDCY2IIJYGE2JUJNHWS22LINVHQMCMNVFD
CWJQIIZVUV2JOVNEOVJLINTW6PIK
ENDOFTEXT

pozdrowienia

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.