What you want is "$(printf ...)"
. Stephane has already written an excellent expose of printf
vs echo
, more of an article than a mere answer, so I won't repeat the whole thing here. Keynotes pertinent to the current question are:
- Stick to POSIX features and it is very portable, and
- It is frequently a shell builtin, in which case you have no external calls or dependencies.
I will also add that it took me quite a while (okay, just a few weeks) to get around to switching from echo
, because I was used to echo
and thought printf
would be complicated. (What are all those %
signs about, huh?) As it turns out, printf
is actually extremely simple and I don't bother with echo
anymore for anything but fixed text with a newline at the end.
Printf Made Easy
There are vast numbers of options for printf
. You can print numbers to specific decimal places of accuracy. You can print multiple fields, each with a specified fixed width (or a minimum width, or a maximum width). You can cause a shell string variable which contains the character sequences \t
or \n
to be printed with those character sequences interpreted as tabs and newlines.
You can do all these things, and you should know they are possible so you can look them up when you need them, but in the majority of cases the following will be all you need to know:
printf
takes as its first argument a string called "format". The format string can specify how further arguments are to be handled (i.e. how they will be formatted). Further arguments, if not referenced at all* within the format argument, are ignored.
Since alphanumeric characters (and others) can be embedded in the format argument and will print as-is, it may look like printf
is doing the same thing as echo -n
but that for some unknown reason it's ignoring all but the first argument. That's really not the case.
For example, try printf some test text
. In this example some
is actually taken as the format, and since it doesn't contain anything special and doesn't tell printf
what to do with the rest of the arguments, they are ignored and all you get printed is some
.
%
followed by a specific letter needs to be used within the format string (the first argument to printf
) to specify what type of data the subsequent arguments contain. %s
means "string" and is what you will use most often.
\n
or \t
within the format translate to newlines and tab characters respectively.
That's really all you need to use printf
productively. See the following code block for some very simple illustrative examples.
$ var1="First"
$ var2="Second"
$ var3="Third"
$ printf "$var1" "$var2" "$var3" # WRONG
First$ # Only the first arg is printed, without a trailing newline
$
$ printf '%s\n' "$var1" # %s means that the next arg will be formatted as a literal string with any special characters printed exactly as-is.
First
$
$ printf '%s' "$var1" "$var2" "$var3" # When more args are included than the format calls for, the format string is reused. This example is equivalent to using '%s%s%s' as the format.
FirstSecondThird$ # All three args were printed; no trailing newline.
$
$ printf '%s\t%s\t%s\n' "$var1" "$var2" "$var3"
First Second Third # Tab separation with trailing newline. This format is very explicit about what to do with three arguments. Now see what happens if four are used:
$ var4="Fourth"
$ printf '%s\t%s\t%s\n' "$var1" "$var2" "$var3" "$var4"
First Second Third # The specified format is reused after the three expected args,
Fourth # so this line has two trailing tabs.
$
$ printf '%s\n' "$var1" "$var2" "$var3" # This format reuse can be used to advantage in printing a list, for example.
First
Second
Third
$
$ printf '%s\t' "$var1" "$var2" "$var3" ; printf '\n' # Here is a dual command that could have args added without changing the format string...
First Second Third
$ printf '%s\t' "$var1" "$var2" "$var3" "$var4" ; printf '\n'
First Second Third Fourth # ...as you can see here.
$ # It does print a trailing tab before the newline, however.
* Of course, if you include a single argument format specifier sequence such as %s
, your whole format string is reused as many times as needed to handle all arguments provided. See examples.
$(printf ...)
for maximum compatibility. See http://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo Advantage overtput
is of course thatprintf
is a shell builtin. – Wildcard Oct 21 '15 at 10:53tput
is the right way to produce terminal control codes. – Toby Speight Oct 21 '15 at 12:40$(printf \\033)
since no one answered the question – nathanfranke Apr 18 '21 at 05:50