title: Programmatically build string for printf
body: <p>I’m trying to build up a colourful line to be printed to my terminal.</p>
  
  <p>I’m writing my message to a file with Ruby.</p>
  
  <pre><code>def warn(line)
    log = File.open("#{File.dirname(__FILE__)}/../../log/import/import.log", "a")
    log.puts("WARN #{line}")
    log.close
  end
  </code></pre>
  
  <p>A typical line written to the log file will look like this:</p>
  
  <pre class="lang-none prettyprint-override"><code>WARN Client insertion failed: [149] Validation failed: Email is invalid
  </code></pre>
  
  <p>I’m continuously reading from this file with <code>tail</code>:</p>
  
  <pre><code>tail -F -n 0 log/import/import.log | script/report.sh
  </code></pre>
  
  <p>The script I’m piping the <code>tail</code> output to looks like this:</p>
  
  <pre><code>#!/bin/bash
  
  set -e
  
  while read LINE; do
    case "$LINE" in
      "file truncated")
        clear
        ;;
      INFO*)
        tput setaf 6
        echo "${LINE:5}"
        tput sgr0
        ;;
      WARN*)
        tput setaf 1
        printf "${LINE:5}" | cut -d ":" -f1
        tput sgr0
        printf ": "
        tput setaf 3
        printf "["
        tput sgr0
        printf "${LINE:5}" | cut -d "[" -f2 | cut -d "]" -f1
        tput setaf 3
        printf "]"
        tput sgr0
        printf "${LINE:5}" | cut -d "]" -f2
        printf "\n"
        ;;
      *)
        echo "$LINE"
        ;;
    esac
  done
  </code></pre>
  
  <p>My output is being printed onto separate lines, so it looks like this:</p>
  
  <p><img src="https://i.stack.imgur.com/B1OKn.png" alt="Current terminal output"></p>
  
  <p>However, I’d like each error to be printed on its own line, like this:</p>
  
  <p><img src="https://i.stack.imgur.com/8FW0i.png" alt="desired output"></p>
  
  <p>How can I make this work?</p>
  
  <hr>
  
  <p>After receiving some excellent answers, I refactored my script to look like this:</p>
  
  <pre><code>#!/bin/bash
  
  set -e
  
  printfg() {
    tput setaf $3
    printf "$1" "$2"
    tput sgr0
  }
  
  while read LINE; do
    case "$LINE" in
      "file truncated")
        clear
        ;;
      INFO*)
        printfg "%s\n" "${LINE:5}" 6
        ;;
      WARN*)
        IFS="[]" read error number reason &lt;&lt;&lt; "$(echo "${LINE:5}")"
        printfg "%s" "$error" 1
        printfg "%s" "[" 3
        printf "%s" "$number"
        printfg "%s" "]" 3
        printf "%s\n" "$reason"
        ;;
      *)
        echo "$LINE"
        ;;
    esac
  done
  </code></pre>