1

If in my terminal I write

cat <<-EOF
hello
EOF

I get the expected output, hello.

Now, In a script I'm writing I have

PARAMS=""
while (( "$#" )); do
  case "$1" in
    -h|--help)
      cat <<-EOF
      hello
      EOF
      exit 0  
      ;;
    --) # end argument parsing
      shift
      ...

But vscode is highlighting everything after the line cat<<-EOF as if it all was a string, basically ignoring the EOF. And in fact when I run the script I get a

syntax error: unexpected end of file

error

Edit:

if I indent the code like this:

while (( "$#" )); do
  case "$1" in
    -h|--help)
      cat <<EOF
      ciao
EOF
      exit 0  
      ;;
    --) # end argument parsing
      shift
      ...

with EOF on the left, vscode recognises it as it should, hilighting the rest of the file as a normal bash script and everithing works. But indentation-wise this sucks. Is there a way to indent EOF with the cat command?

ninazzo
  • 547
  • 1
  • 6
  • 17
  • Can you try to put a `tab` in front of EOF ? – Philippe Apr 19 '20 at 17:00
  • @Philippe what's a ? – ninazzo Apr 19 '20 at 17:01
  • 1
    Pretty sure the EOF has to begin the line. – stark Apr 19 '20 at 17:02
  • 1
    with tab in front of EOF there's still the problem. It only works when EOF is at the beginning of the line like @stark says. – ninazzo Apr 19 '20 at 17:03
  • 3
    Make sure you have put a `tab`, from doc `If the redirection operator is <<-, then all leading tab characters are stripped from in- put lines and the line containing delimiter. This allows here-documents within shell scripts to be indented in a natural fashion.` I just tested your code, it works with a `tab`. – Philippe Apr 19 '20 at 17:05

2 Answers2

5

You could to use spaces before EOF in here-doc like this:

    cat <<"    EOF"
        foo
        bar
    EOF

But to avoid formatting/indentation issues I prefer to use functions for that:

print_help() {
cat <<EOF
    foo
    bar
EOF
}
...
PARAMS=""
while (( "$#" )); do
  case "$1" in
    -h|--help)
      print_help
      exit 0  
      ;;
    --) # end argument parsing
      shift
      ...

It also makes code cleaner.

Abelisto
  • 14,826
  • 2
  • 33
  • 41
2

The -EOF has to be at the beginning of the line. I've made that mistake several times when I prettyprint a script and inadvertently indent the heredoc terminator.

Richard Jessop
  • 897
  • 1
  • 12
  • 19
  • 2
    Cannot create a new answer, so i'm adding this comment. This is not the problem here... he used `<<-EOF` in which the dash means that you CAN indent the heredoc terminator... The actual problem is that you **must use TABS** when indenting the terminator (as you can see [here](https://unix.stackexchange.com/a/76483/348102) and as said by @Philippe) and probably @ninazzo used spaces. Another thing is that the terminator CANNOT be followed by **any** character or it will break – LukeSavefrogs Jun 01 '20 at 07:19
  • Note: the original problem statement has a - in front of the EOF. Later in the problem statement, the - is omitted. The answer still stands that the terminator must occur at the beginning of the line (and with nothing else following it). Indiscriminant prettyprinting of bash scripts is not a general safe practice. – Richard Jessop Jun 01 '20 at 15:18