Bash printf formating not working

For example, the c format does not work.
I’m input printf "ABCctest" to bash console and result;

ABCctest

Considering the c format’s property, the expected output should be in the form of just ABC.

Nor did I find a proper source that detailed the use of the printf command on bash. Also, as in the above example, the properties on the man page specified for the printf command do not work correctly.

Please show me a source on bash that explains the printf command in detail. Because I’m so confused right now.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

printf 'ABCctest'

You’ve hit upon one of the unspecified parts of the printf command, whose behaviour varies from implementation to implementation. You’re putting the c in the wrong place.

If you read the Single Unix Specification‘s description of printf carefully, you will see that c is not listed in the list of escape sequences that are defined for the format string (the first argument to the command). Rather, it is defined as an extra escape sequence that is recognized when given in an argument string that is to be formatted by the %b format specifier.

In other words:

  • printf '%bn' 'ABCctest' has a well specified behaviour. The c causes everything remaining (including the newline in the format string) to be ignored.
  • printf '%sn' 'ABCctest' has a well specified behaviour. The c is not an escape sequence in the first place.
  • printf 'c' does not have a well specified behaviour. The SUS is simply silent upon what c is, not listing it as an escape sequence but also not saying in its File Format Notation section that such a sequence is never an escape sequence.

How different shells behave in response to this non-conformant format string varies quite significantly. Here are the Debian Almquist, Bourne Again, FreeBSD Almquist, Korn ’93, and Z shells’ reactions (with %s showing where no newlines have been emitted):

% dash -c "printf 'ABCctestn'"
ABCctest
% bash -c "printf 'ABCctestn'"
ABCctest
% sh -c "printf 'ABCctestn'"
ABC%
% ksh93 -c "printf 'ABCctestn'"
ABCest
% zsh -c "printf 'ABCctestn'"
ABC%
%

The builds of the MirBSD Korn and PD Korn shells that I have do not have a printf built-in command. The FreeBSD non-built-in printf does this:

% /usr/bin/printf 'ABCctestn'
ABC%
%

Adding to the fun is that the doco for the various shells is sometimes highly misleading and even sometimes downright erroneous. For examples:

  • The Z shell doco only recently started to give a correct description of what c does, and lists it (via its doco for echo) as an escape sequence allowed in format strings. (It was incorrect until 2017, the doco neither agreeing with the SUS nor describing what the Z shell actually did.)
  • The Korn ’93 shell doco gives a description that is in line with the SUS, but it is not (as can be seen in the aforegiven) what it actually does when c is in the format specifier. It, too, documents c as an escape sequence for the format string. Its behaviour is clearly a bug.
  • The doco for the Bourne Again shell and the doco for the Debian Almquist shell give a description of c that matches the SUS and explicitly list it in relation to %b (in the case of the Bourne Again shell more clearly than it does now up until 2016) and not in a general list of escape sequences for printf format specifiers. These shells do not provide this as an extension to the standard.
  • The FreeBSD Almquist shell doco defers to the FreeBSD external printf command manual, whose description of c is in line with the SUS. It explicitly lists it as an escape sequence allowed in format strings, and its actual behaviour is as documented in the user manual.

The FreeBSD Almquist shell and (recent) Z shell are the only shells, here, that both document allowing c as an escape sequence in format strings (an extension to what is defined by the standard) and actually behave as they are documented.

Ironic further reading

Method 2

It is necessary to expand backslash escape sequences in the corresponding argument.
As stated in here:

c  Terminate output similarly to the c escape used by echo -e. printf produces no additional output after coming across a c escape in a %b argument.
$ printf "%bn" "ABCchi"
ABC


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x