Здесь-документ дает ошибку "неожиданный конец файла"
Мне нужен мой скрипт для отправки электронного письма с терминала. Основываясь на том, что я видел здесь и во многих других местах в Интернете, я отформатировал его так:
/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
Однако, когда я запускаю это, я получаю это предупреждение:
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
... где строка x - последняя записанная строка кода в программе, а строка y - строка с /var/mail
в этом. Я пытался заменить EOF
с другими вещами (ENDOFMESSAGE
, FINISH
и т. д.) но безрезультатно. Почти все, что я нашел в Интернете, было сделано именно так, и я действительно новичок в bash, поэтому мне сложно разобраться в этом самостоятельно. Может ли кто-нибудь предложить какую-либо помощь?
10 ответов
EOF
токен должен быть в начале строки, вы не можете сделать отступ вместе с блоком кода, с которым он идет.
Если ты пишешь <<-EOF
Вы можете сделать отступ, но он должен содержать отступы, а не пробелы. Так что это все еще может не закончиться даже с блоком кода.
Также убедитесь, что у вас нет пробелов после EOF
жетон на линии.
Строка, которая начинает или заканчивает Here-Doc, вероятно, содержит некоторые непечатаемые или пробельные символы (например, возврат каретки), что означает, что второй "EOF" не совпадает с первым, и не заканчивается должно. Это очень распространенная ошибка, которую трудно обнаружить с помощью текстового редактора. Вы можете сделать непечатные символы видимыми, например, с помощью cat
:
cat -A myfile.sh
Как только вы увидите выход из cat -A
решение будет очевидным: удалите оскорбительные символы.
Пожалуйста, попробуйте удалить предыдущие пробелы, прежде чем EOF
:-
/var/mail -s "$SUBJECT" "$EMAIL" <<-EOF
С помощью <tab>
вместо <spaces>
для идентификации и использования << - EOF работает нормально.
"-"
удаляет <tabs>
не <spaces>
, но по крайней мере это работает.
Для тех, кто спотыкается здесь, кто гуглил «предупреждение bash: здесь-документ, разделенный концом файла» , возможно, вы получаете
предупреждение: здесь-документ в строке 74 разделен концом файла
... введите предупреждение, потому что вы случайно использовали здесь символ документа (
<<
), когда вы хотели использовать строковый символ здесь (
<<<
). Это был мой случай.
Обратите внимание, что при этом также может появиться эта ошибка;
while read line; do
echo $line
done << somefile
Потому как << somefile
должен прочесть < somefile
в этом случае.
Может быть, это старо, но у меня был пробел после окончания EOF << EOFblahblahEOF <- вот в чем проблема. Прошло много лет, наконец-то посмотрел здесь
Когда я хочу иметь строки документации для моих функций bash, я использую решение, подобное предложению ace в дубликате этого вопроса.
Посмотрите, как я определяю ИСПОЛЬЗОВАНИЕ для решения, которое:
- автоформатирование хорошо для меня в моей выбранной среде IDE (возвышенное)
- многострочный
- может использовать пробелы или табуляции в качестве отступов
- сохраняет отступы в комментарии.
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"
}
Так
foo -h
дает:
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
Объяснение
cut -d "#" -f 2
: Получить вторую часть
#
линии с разделителями. (Представьте, что CSV с символом "#" в качестве разделителя, пустой первый столбец).
cut -c 2-
: Получить второй до конца символ результирующей строки
Также обратите внимание, что
if [ "$1" = "-h" ]
оценивается как
False
если нет первого аргумента, без ошибки, так как он становится пустой строкой.
убедитесь, что вы помещаете конечный EOF, вы помещаете его в начало новой строки
Наряду с другими ответами, упомянутыми Бармаром и Джони, я заметил, что мне иногда приходится оставлять пустую строку до и после моего EOF при использовании <<-EOF
,
Вот гибкий способ справиться с несколькими строками с отступом без использования 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
Некоторые примечания к этому решению:
- если ожидается, что в контенте будут простые кавычки, либо экранируйте их, используя
\
или замените разделители строк двойными кавычками. В последнем случае будьте осторожны, чтобы конструкция вроде$(command)
будут интерпретированы. Если строка содержит как простые, так и двойные кавычки, вам придется экранировать хотя бы вид. - в данном примере напечатайте завершающую пустую строку, есть множество способов избавиться от нее, не включенные здесь, чтобы свести предложение к минимуму беспорядка
- гибкость проистекает из легкости, с которой вы можете контролировать, сколько ведущего места должно оставаться или уходить, при условии, конечно, что вы знаете некоторый sed REGEXP.