1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Backport 'printf -v' from ksh 93v-

'printf' on bash and zsh has a popular -v option that allows
assigning formatted output directly to variables without using a
command substitution. This is much faster and avoids snags with
stripping final linefeeds. AT&T had replicated this feature in the
abandoned 93v- beta version. This backports it with a few tweaks
and one user-visible improvement.

The 93v- version prohibited specifying a variable name with an
array subscript, such as printf -v var\[3\] foo. This works fine on
bash and zsh, so I see no reason why this should not work on ksh,
as nv_putval() deals with array subscripts just fine.

src/cmd/ksh93/bltins/print.c: b_print():
- While processing the -v option when called as printf, get a
  pointer to the variable, creating it if necessary. Pass only the
  NV_VARNAME flag to enforce a valid variable name, and not (as
  93v- does) the NV_NOARRAY flag to prohibit array subscripts.
- If a variable was given, set the output file to an internal
  string buffer and jump straight to processing the format.
- After processing the format, assign the contents to the string
  buffer to the variable.

src/cmd/ksh93/data/builtins.c:
- Document the new option, adding a warning that unquoted square
  brackets may trigger pathname expansion.
This commit is contained in:
Martijn Dekker 2021-11-18 23:36:28 +01:00
parent fb8308243c
commit bd9752e43c
5 changed files with 48 additions and 6 deletions

View file

@ -1298,5 +1298,18 @@ got="$($SHELL -i "$hist_error_leak" 2>&1)"
[[ $exp == "$got" ]] || err_exit "file descriptor leak after substitution error in hist builtin" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
# ======
# printf -v works as of 2021-11-18
integer ver=.sh.version
exp=ok$'\f'0000$ver$'\n'
printf -v got 'ok\f%012d\n' $ver 2>/dev/null
[[ $got == "$exp" ]] || err_exit "printf -v not working" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
unset got
printf -v 'got[1][two][3]' 'ok\f%012d\n' $ver 2>/dev/null
[[ ${got[1]["two"][3]} == "$exp" ]] || err_exit "printf -v not working with array subscripts" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
unset got ver
# ======
exit $((Errors<125?Errors:125))