6

I wanted to see how some ASCII art looked in terminal so:

$ cat <<EOF                                                                                                                                                                                  
> #          ____         _
> #  _   _  / __/  ___ _ | |_
> # | | | |/ /    /  _` || __|
> # | |_| |\ \__ 🐱 (_| || |_
> # |  _,_| \___\ \___,_| \__|
> # |_/
> #
> EOF
bash: bad substitution: no closing "`" in ` || __|
# | |_| |\ \__ 🐱 (_| || |_
# |  _,_| \___\ \___,_| \__|
# |_/
#

The # octothorpes were there perchance, but now I'm confused.

$ cat <<EOF
> # echo hi
> EOF
# echo hi

As expected.

However:

$ cat <<EOF
> # `echo hello`
> EOF
# hello

So bash gets at expanding `` and $( ) before cat does, but it doesn't care about # comments? What's the explanation behind this behaviour?

  • 5
    Change cat <<EOF to cat <<\EOF. – jimmij Jan 29 '16 at 0:34
  • 2
    If the commented line was output, then clearly it's not a comment. – muru Jan 29 '16 at 0:37
  • @muru I don't mean a comment in that cat will ignore it, I meant a comment to be ignored by bash. – cat Jan 29 '16 at 0:37
  • 1
    Since cat doesn't have any concept of comments at all, we're both talking of bash. A comment shouldn't affect the outcome at all. If it does, it's not a comment. – muru Jan 29 '16 at 0:39
  • 1
    @mikeserv i am the macro cat :) microcat – cat Jan 29 '16 at 1:09
16

This is more general than bash. In POSIX shell, your EOF is referred to as a word, in the discussion of here-documents:

If no characters in word are quoted, all lines of the here-document shall be expanded for parameter expansion, command substitution, and arithmetic expansion. In this case, the <backslash> in the input behaves as the <backslash> inside double-quotes (see Double-Quotes). However, the double-quote character ( '"' ) shall not be treated specially within a here-document, except when the double-quote appears within "$()", "``", or "${}".

Quoting is done using single-, double-quotes or the backslash character. POSIX mentions the here-documents in the discussion of quoting:

The various quoting mechanisms are the escape character, single-quotes, and double-quotes. The here-document represents another form of quoting; see Here-Document.

The key to understanding the lack of treatment of # characters is the definition for here-documents:

allow redirection of lines contained in a shell input file

That is, no meaning (other than possible parameter expansion, etc) is given to the data by the shell, because the data is redirected to another program: cat, which is not a shell interpreter. If you redirected to a shell program, the result would be whatever the shell could do with the data.

  • 3
    Perhaps better reason why # does not introduce comment in here-document is that it does not introduce comment in quoted string either and here-documents behave as quoted strings. – Jan Hudec Jan 29 '16 at 7:56
  • For that, you have to do more reading between the lines, because POSIX does not mention comments and quoting in the same sentence (I think). Redirecting was the closest I found. – Thomas Dickey Jan 29 '16 at 9:36
  • A # does not introduce a comment in a here document for the same reason it does not introduce a comment in "# $(echo foo)": a string is data, not code. – chepner Jan 29 '16 at 16:36
8

Within a here document there are no comment lines.

man bash:

No parameter and variable expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, the character sequence \ is ignored, and \ must be used to quote the characters \, $, and `.

So you need:

cat <<"EOF"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.