Potrzebuję mojego skryptu, aby wysłać wiadomość e-mail z terminala. Opierając się na tym, co widziałem tutaj i wielu innych miejscach online, sformatowałem to w następujący sposób:
/var/mail -s "$SUBJECT" "$EMAIL" << EOF
Here's a line of my message!
And here's another line!
Last line of the message here!
EOF
Jednak gdy to uruchomię, otrzymuję to ostrzeżenie:
myfile.sh: line x: warning: here-document at line y delimited by end-of-file (wanted 'EOF')
myfile.sh: line x+1: syntax error: unexpected end of file
... gdzie linia x to ostatnia zapisana linia kodu w programie, a linia y to linia, /var/mail
w której się znajduje. Próbowałem wymianie EOF
z innymi ( ENDOFMESSAGE
, FINISH
, itd.), Ale bezskutecznie. Prawie wszystko, co znalazłem w Internecie, działa w ten sposób, a ja jestem naprawdę nowy w bash, więc ciężko mi to rozgryźć samodzielnie. Czy ktoś mógłby zaoferować pomoc?
EOF
wiersz jest wcięty? Musi być na początku linii.<<-EOF
- gnu.org/software/bash/manual/bashref.html#Here-DocumentsOdpowiedzi:
EOF
Żeton musi być na początku linii, nie można wciąć go wraz z blokiem kodu to idzie z.Jeśli piszesz
<<-EOF
, możesz wciąć go, ale musi być wcięty za pomocą Tabznaków, a nie spacji. Więc nadal może nie skończyć się nawet z blokiem kodu.Również upewnić się, że nie ma spacji po
EOF
żeton na linii.źródło
dos2unix
aby to naprawić.Linia, która zaczyna lub kończy dokument tutaj, prawdopodobnie zawiera jakieś niedrukowalne lub białe znaki (na przykład powrót karetki), co oznacza, że drugi „EOF” nie pasuje do pierwszego i nie kończy dokumentu tutaj, jak powinno. Jest to bardzo częsty błąd i trudny do wykrycia za pomocą samego edytora tekstu. Możesz sprawić, że znaki niedrukowalne będą widoczne, na przykład za pomocą
cat
:Gdy zobaczysz wyjście z
cat -A
rozwiązania, będzie oczywiste: usuń obraźliwe znaki.źródło
Spróbuj usunąć poprzedzające spacje przed
EOF
: -/var/mail -s "$SUBJECT" "$EMAIL" <<-EOF
Używanie
<tab>
zamiast<spaces>
ident AND używanie << - EOF działa dobrze."-"
Usuwa<tabs>
, nie<spaces>
, ale przynajmniej to działa.źródło
Zauważ, że możesz również otrzymać ten błąd, jeśli to zrobisz;
while read line; do echo $line done << somefile
Bo
<< somefile
powinienem przeczytać< somefile
w tym przypadku.źródło
Oto elastyczny sposób radzenia sobie z wieloma wierszami z wcięciem bez użycia heredoc.
echo 'Hello!' sed -e 's:^\s*::' < <(echo ' Some indented text here. Some indented text here. ') if [[ true ]]; then sed -e 's:^\s\{4,4\}::' < <(echo ' Some indented text here. Some extra indented text here. Some indented text here. ') fi
Kilka uwag na temat tego rozwiązania:
\
zastąp je znakami cudzysłowu lub zastąp je podwójnymi cudzysłowami. W tym drugim przypadku należy uważać, aby podobna konstrukcja$(command)
została zinterpretowana. Jeśli ciąg zawiera zarówno cudzysłowy proste, jak i cudzysłowy, musisz przynajmniej uciec.źródło
Kiedy chcę mieć ciągi dokumentacyjne dla moich funkcji bash, używam rozwiązania podobnego do sugestii user12205 w duplikacie tego pytania.
Zobacz, jak definiuję USAGE dla rozwiązania, które:
function foo { # Docstring read -r -d '' USAGE <<' END' # This method prints foo to the terminal. # # Enter `foo -h` to see the docstring. # It has indentations and multiple lines. # # Change the delimiter if you need hashtag for some reason. # This can include $$ and = and eval, but won't be evaluated END if [ "$1" = "-h" ] then echo "$USAGE" | cut -d "#" -f 2 | cut -c 2- return fi echo "foo" }
Więc
foo -h
daje:This method prints foo to the terminal. Enter `foo -h` to see the docstring. It has indentations and multiple lines. Change the delimiter if you need hashtag for some reason. This can include $$ and = and eval, but won't be evaluated
Wyjaśnienie
cut -d "#" -f 2
: Pobierz drugą część#
rozdzielonych linii. (Pomyśl o csv z „#” jako separatorem, pustą pierwszą kolumnę).cut -c 2-
: Pobierz drugi do końca znak wynikowego ciąguZauważ również, że
if [ "$1" = "-h" ]
obliczane jest tak,False
jakby nie było pierwszego argumentu, bez błędu, ponieważ staje się pustym ciągiem.źródło
Wraz z innymi odpowiedziami wymienionymi przez Barmara i Joni zauważyłem, że czasami muszę zostawić pustą linię przed i po moim EOF podczas używania
<<-EOF
.źródło
cat
i ze względu na formatowanie, tuż przed moim zamykającym znacznikiem here-doc, musiałem dodać enter przed zamykającym parenem, w przeciwnym razie dostałbym tę niezgodność. Głosowanie za głosami jest całkowicie ważne dla „niektórych” ludzi, choć prawdopodobnie jest to mało prawdopodobny scenariusz.