Subject: Re: bug#65659: RFC: changing printf(1) behavior on %b

From: Steffen Nurpmeso <[email-masked]>
Date: Sat, 02 Sep 2023 19:57:11 +0200

Stephane Chazelas wrote in
 <[email-masked]>:
 |2023-09-01 23:28:50 +0200, Steffen Nurpmeso via austin-group-l at The \
 |Open Group:
 ...
 |>|FWIW, a "printf %b" github shell code search returns ~ 29k
 |>|entries
 |>|(https://github.com/search?q=printf+%25b+language%3AShell&type=code&l=Sh\
 |>|ell)
 ...
 |> Actually this returns a huge amount of false positives where
 |> printf(1) and %b are not on the same line, let alone the same
 ...
 |Apparently, we can also search with regexps and searching for
 |printf.*%b
 |(https://github.com/search?q=%2Fprintf.*%25b%2F+language%3AShell&type=code)
 |It's probably a lot more accurate. It returns ~ 19k.
 ...
 |> Furthermore it shows a huge amount of false use cases like
 ...
 |Yes, I also see a lot of echo -e stuff that should have been
 |echo -E stuff (or echo alone in those (many) implementations
 |that don't expand by default or use the more reliable printf
 |with %s (not %b)).
 |
 |> It seems people think you need this to get colours mostly, which
 ...
 |Incidentally, ANSI terminal colour escape sequences are somewhat
 |connecting those two %b's as they are RGB (well BGR) in binary
 |(white is 7 = 0b111, red 0b001, green 0b010, blue 0b100), with:
 |
 |R=0 G=1 B=1
 |printf '%bcyan%b\n' "\033[3$(( 2#$B$G$R ))m" '\033[m'
 |
 |(with Korn-like shells, also $(( 0b$B$G$R )) in zsh though zsh
 |has builtin colour output support including RGB-based).

..and, off-topic, but in my opinion that is also false usage, one
should use tput(1) instead, and then simply printf(1) (or echo(1)
(or cat(1))) the output, something like, fwiw :),

  color_init() {
          [ -n "${NO_COLOUR}" ] && return
          # We do not want color for "make test > .LOG"!
          if [ -t 1 ] && command -v tput >/dev/null 2>&1; then
                  { sgr0=$(tput sgr0); } 2>/dev/null
                  [ $? -eq 0 ] || return
                  { saf1=$(tput setaf 1); } 2>/dev/null
                  [ $? -eq 0 ] || return
                  { saf2=$(tput setaf 2); } 2>/dev/null
                  [ $? -eq 0 ] || return
                  { saf3=$(tput setaf 3); } 2>/dev/null
                  [ $? -eq 0 ] || return
                  { saf5=$(tput setaf 5); } 2>/dev/null
                  [ $? -eq 0 ] || return
                  { b=$(tput bold); } 2>/dev/null
                  [ $? -eq 0 ] || return

                  COLOR_ERR_ON=${saf1}${b} COLOR_ERR_OFF=${sgr0}
                  COLOR_DBGERR_ON=${saf5} COLOR_DBGERR_OFF=${sgr0}
                  COLOR_WARN_ON=${saf3}${b} COLOR_WARN_OFF=${sgr0}
                  COLOR_OK_ON=${saf2} COLOR_OK_OFF=${sgr0}
                  unset saf1 saf2 saf3 b
          fi
  }

  ...

  printf '%s%s%s' "${COLOR_WARN_ON}" "$SOME_MSG" "${COLOR_WARN_OFF}"

Of course this is also only ANSI via sgr0 (:-|

 |Speaking of stackexchange, on the June data dump of
 |unix.stackexchange.com:
 |
 |stackexchange/unix.stackexchange.com$ xml2 < Posts.xml | grep -c 'printf\
 |.*%b'
 |494
 |
 |(FWIW)
 |
 |Compared with %d (though that will have entries for printf(3) as well):
 |
 |stackexchange/unix.stackexchange.com$ xml2 < Posts.xml | grep -c 'printf\
 |.*%d'
 |3444

I am totally stunned by the ratio.  I myself have never used %b
(like this, aka for printf).

 --End of <[email-masked]>

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)