I have a simple debug_print shell function that I use to help write larger shell scripts. In general, I try to write only Bourne-compatible scripts and avoid Bash-isms. In this case, the Bash version of my debug_print function works fine, but I cannot for the life of me figure out why my Bourne-compatible version fails. Specifically, my problems are with using the %s format modifier with printf.
I've included my test script below. The debug_print function displays a header bar with a label, the contents of its string or file argument, and finally a footer bar with the same width as the header. The problems are with displaying the footer bar and begin with the comment "Display a footer line...". The two uncommented lines following that are what I believe should work, but do not.
Following that are several commented lines under the "None of these work" comment where you can see some of the various tests/variances I used while trying to figure out the problem. After those lines are a working Bourne version, and, finally, a working Bash version.
I've read the manpages in painful detail and tried every variety of format string, quoting, and variable use I can think of. So far, none of these attempts is working right. Under the "None of these work" comment, the none working commands all print out the entire string instead of, as I believe they should, only the number of characters specified by the field width modifier.
To determine "Bourne compatibility" I use dash as /bin/sh on my system, which is typical of Debian systems. Dash is meant for efficient script execution and not interactive use. According to the manpage, it strives for strict Bourne compatibility, so I have reasoned that if my script works with dash then it should be reasonably Bourne compatible and free of bash-isms. Also, I recognize that this function is not the be-all/end-all of debug printing and there are likely numerous corner cases and areas where it could be improved. I welcome all suggestions, but I am particularly interested in this printf problem. Given how simple this should be, it seems like I must be making some stupid mistake, but I cannot spot it.
Here is my debug_print test script:
#!/bin/sh
#
# Purpose: Debug print function. Outputs delimiting lines and will display
# either the contents of a file or the contents of a variable.
#
# Usage: debug_print label input
# Where label is the title to print in the header bar, usually the name of
# the input variable. Input is either a file on disk to be printed, or,
# if the argument is not a file then it is assumed to be a string and that
# will be displayed instead.
#
# Returns: If two parameters are not provided, returns false, otherwise it
# will always return true.
#
debug_print()
{
local header_bar header_len dashes
# Check for arguments
if [ $# -ne 2 ]; then
printf "Error: debug_print takes two parameters: 'label' and 'input'\n"
return 1
fi
header_bar="-------------------------$1-------------------------"
header_len=${#header_bar}
printf "%s\n" "$header_bar"
# Display either the contents of the input file or the input string
if [ -r "$2" ]; then
cat "$2"
else
printf "%s\n" "$2"
fi
# Display a footer line with the same length as the header line
dashes="------------------------------------------------------------"
printf "%*s\n" "$header_len" "$dashes"
# None of these work
# printf "%${header_len}s\n" "$dashes"
# printf "%${header_len}s\n" "------------------------------------------------------------"
# printf "%5s\n" xxxxxxxxxxxxxxxxxxxx
# printf '%5s\n' "xxxxxxxxxxxxxxxxxxxx"
# xxx="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# printf '%5s\n' $xxx
# This works with dash
# i=$header_len
# while [ $i -gt 0 ]; do
# printf "-"
# i=$(( $i - 1 ))
# done
# printf "\n"
# Working bash version
# printf -v foot_line '%*s' $header_len
# echo ${foot_line// /-}
return 0
}
# Test debug printing
debug_print "Label" "The contents of the debug input..."
Thanks for any help.