Search code examples
bashprintfvariadic-functions

How to write a function with a variable number of arguments that are passed to printf


How do I fix the print_error function below:

#!/bin/bash

script_name="tmp.bash"

function print_error {
    format="$1"
    shift
    printf "%s: ERROR: %s\n" "$script_name" "$format" "$@"
}

print_error "Today is %s; tomorrow is %s" "$(date)" "$(date -d "+1 day")"

so that it outputs:

tmp.bash: ERROR: Today is Mon Nov 22 15:10:40 PST 2021; tomorrow is Tue Nov 23 15:10:50 PST 2021

Currently, it outputs:

tmp.bash: ERROR: Today is %s; tomorrow is %s
Mon Nov 22 15:10:40 PST 2021: ERROR: Tue Nov 23 15:10:50 PST 2021

print_error should be able to accept a variable number of arguments.


Solution

  • Use an intermediate variable (here substr) to build the functional message (date message) and a second buid for the technical message (error message):

    #! /bin/bash
    
    declare -r script_name="tmp.bash"
    
    function print_error {
        local substr=
        printf -v substr "$1" "${@:2}"
        printf "%s: ERROR: %s\n" "$script_name" "$substr"
    }
    
    print_error "Today is %s; tomorrow is %s" "$(date)" "$(date -d "+1 day")"
    

    Than, you can separate functional and technical builds:

    #! /bin/bash
    
    declare -r script_name="tmp.bash"
    
    function print_tech_error () {
        printf "%s: ERROR: %s\n" "$script_name" "$1"
    }
    function print_fct_error {
        local substr=
        printf -v substr "$1" "${@:2}"
        print_tech_error "${substr}"
    }
    
    print_fct_error "Today is %s; tomorrow is %s" "$(date)" "$(date -d "+1 day")"