Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there something better than <<- EOF in bash?

I recently tried to use the <<- operator for heredocs in bash to keep indentation in my bash functions:

cat <<- EOF
    Hello World
EOF

However it turns out this only strips literal tab characters before the strings, which is of no use to me since:

  1. Some code editors replace tabs with spaces right away. So when I save this text in nvim or vscode it will still keep the indentation
  2. the EOF still needs to be written left-bound, I can't indent it.

I also don't want to strip all whitespace, only the ones that match up to the height of the EOF delimiter. So this would be my use case:

#!/bin/bash

log_something() {
    cat <<- EOF
    This is not indented in the final document
        This is indented by 4 spaces
    EOF
}

log_something

Is something like this possible in modern bash?

like image 529
glades Avatar asked Nov 01 '25 02:11

glades


2 Answers

This is more of a hack than a recommendable solution, but you could simply make the termination string already contain the indenting spaces itself, i.e. using EOF, and replace the plain cat with a cut -c5- to un-indent the content block:

#!/bin/bash

log_something() {
    cut -c5- <<- "    EOF"
    This is not indented in the final document
        This is indented by 4 spaces
    EOF
}

log_something
This is not indented in the final document
    This is indented by 4 spaces
like image 110
pmf Avatar answered Nov 02 '25 16:11

pmf


Function definitions themselves can include input redirections. You can write

log_something() {
    cat
} << EOF
This is not indented in the final document
    This is indented by 4 spaces
EOF

and cat inherits its standard input from the function itself.

(Note that these redirections attached to the definition cannot be overridden by a call to the function, though. log_something <<< "ha ha" still outputs your two lines of text, not ha ha.)

If you needed different inputs for different commands, you can use different file descriptors. For example,

foo () {
  cat <&3
  echo "==="
  cat <&2
} 2<<EOF2 3<<EOF3
second cat
EOF2
first cat
EOF3

Then

$ foo
first cat
===
second cat

This takes advantage of the fact that you can start multiple here documents (each associated with a different file descriptor) at the same time and complete them in starting order one after the other. Inside the function, each cat redirects its standard input from the appropriate here document's file descriptor.

like image 32
chepner Avatar answered Nov 02 '25 16:11

chepner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!