9

If I have some nested and indented statements that echo a multi-line string into a file, the indents from the original shell (in my case bash) will be carried over into the target file.

To avoid this, I remove indents from the echo'ed output, but this loses that indented code formatting in my source, for example,

#! /bin/bash

function configure_default_vhost() {

    case "$2" in
        [--production])
              echo "<VirtualHost *:80>
# These lines are "breaking" out of the preffered indenting
redirect 404 /
ErrorDocument 404
</VirtualHost>
" > /etc/apache/sites-availabe/000-default.conf
    esac
}

I'm aiming to get something as close as possible to this:

#! /bin/bash

function configure_default_vhost() {

    case "$2" in
        [--production])
              echo "<VirtualHost *:80>
                    # These lines are aligned with the preffered indenting
                    redirect 404 /
                    ErrorDocument 404
                    </VirtualHost>
                    " > /etc/apache/sites-availabe/000-default.conf
    esac
}

(Note: this question has been listed as a possible duplicate of a HEREDOC related question. I'm not sure where the correct place to respond to this is so I'll put here for now (someone please let know if otherwise). My question is about indenting code blocks, and heredoc is only one of the many ways to acheive this and actually HEREDOC wasn't the solution I went with.)

  • 2
    Try using a heredoc with a minus sign (e.g. cat <<-EOF). See http://unix.stackexchange.com/questions/76481/cant-indent-heredoc-to-match-nestings-indent for details. – Mikel Apr 24 '15 at 14:09

3 Answers3

12

You can use a "here-document" with the - modifier. It can be indented by tab characters. You must switch from echo to cat.

cat <<-EOF > /etc/apache/sites-availabe/000-default.conf
        <VirtualHost *:80>
        redirect 404 /
        ErrorDocument 404     
        </VirtualHost>
EOF

Or, to keep tabs in the result, you can pre-process the HERE document by let's say sed and indent with 4 spaces instead:

sed 's/^    //' <<EOF
....{
....(------)func () {
....(------)return
....(------)}
....}
EOF

I used . instead of a space and (------) instead of a tab to show how to format the script.

choroba
  • 47,233
  • nice one, I will test in a script now, is it possible to add back in tabs using here-document so that the the resulting file can have tabs/indents? I guess the heredoc - modifier only removes a fixed number of indents and therefore you can just write your text with tabs and those tab will naturally be included in output? – the_velour_fog Apr 24 '15 at 14:14
  • @user4668401: Unfortunately, all leading tabs are removed. – choroba Apr 24 '15 at 14:19
  • @user4668401: Check the update. – choroba Apr 24 '15 at 14:27
  • 1, I tried your sed idea to post process the target file i.e. sed -i /\-----\-----\-------//g and that worked, but with HEREDOC keep getting error: line delimited by end of file wanted EOF, unexpected end of file
  • – the_velour_fog Apr 24 '15 at 16:02
  • 1
    @user4668401: The final EOF must be left aligned, unless you use <<-EOF and indent the final EOF with tabs only. – choroba Apr 24 '15 at 16:12
  • +1 Avoiding a discussion how you indent, I use \s+. Actually I can fill a multiline variable with my_var=$(sed -r 's/^\s+//' << END , next lines content, the line with END and the next line ). – Walter A Jun 03 '21 at 10:00