I ran across a problem formatting the output during runtime while preserving the format of the code in some scripts. The below works for me, just wanna check that it's reasonable? It seems to dirty up the code a bit, I'd be interested in a better solution - I don't want to create an over complicated bash function that handles every possible use-case for the sake of formatting a few lines. I'd be interested in a portable solution that allows for clean code and predictable output.

printf "\nLine one....
Line 2 - output on next line
Line 3, output on its own newline"

I noticed that printf picks up on the newlines automatically, including your indentation, which allows for easy formatting of output within the file, but can work against your formatting within your script, if you are working in an indented block -

if [ $# -ne 1 ]; then
  printf "\nLine one...
Line 2 - output on next line
Line 3, output on its own newline"

Had I indented Lines 2 and 3 appropriately within their block, printf would have picked up the spaces (tabs) and output them in my script message at runtime.

Can I do something like this, splitting up lines but preserving my format both within my script and within my output? I'd like to keep my lines under 80 characters in width, within reason, but I want to also use printf formatting as normal, controlling newlines with \n instead of the lack of quotes picking up on my newlines automatically. Is multiple printf statements the only way to do this?

Edit / solution code below this line

Referring to l0b0's accepted answer below, I used the %b argument opposed to %s, and initialized the 'lines' variable with double quotes instead of single quotes. The %b arg allowed printf to parse the escape sequences within my lines, and double quotes seemed to allow for the passing of local variables I had created earlier to simplify colorizing output for success / error messages.

RED=$(tput setaf 1)
NORMAL=$(tput sgr0)
lines=( "\nEnter 1 to configure vim with the Klips repository, any other value to exit." \
  "The up-to-date .vimrc config can be found here: https://github.com/shaunrd0/klips/tree/master/configs" \
  "${RED}Configuring Vim with this tool will update / upgrade your packages${NORMAL}\n")

printf '%b\n' "${lines[@]}"
read cChoice

To clarify my indentation / spacing within this question - vim is configured to expand tab symbols to spaces with the below lines in .vimrc -

" Double-quotes is a comment written to be read
" Two Double-quotes ("") is commented out code and can be removed or added

" Set tabwidth=2, adjust Vim shiftwidth to the same
set tabstop=2 shiftwidth=2 

" expandtab inserts spaces instead of tabs
set expandtab 

1 Answer 1


If you use Tab characters for indentation (all but extinct nowadays) you can use this trick in here documents:

if …
    cat <<- EOF

If you replace four spaces with tabs in that command it'll print the same as printf '%s\n' first second.

That said, printf '%s\n' … is probably a much easier solution – that way each line is a separate argument to printf:

$ lines=('Line one...' 'Line 2 - output on next line' 'Line 3, output on its own newline')
$ printf '%s\n' "${lines[@]}"
Line one...
Line 2 - output on next line
Line 3, output on its own newline
  • Hey, thanks for the help here! This worked perfect for me. I had to tweak it slightly to fit my script.. I'll update my question with the solution code to clarify my changes for anyone else in the future looking for the same. Hope my slight changes isn't somehow incorrect - I am rather new to scripting and only use it to automate things on my own servers for fun.
    – null
    Aug 5, 2019 at 8:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .