Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH?] Nofork and removing newlines



2024-03-04 21:52:02 -0800, Bart Schaefer:
[...]
>    mytt($(command)) removes trailing newlines from the output of mytt(command)
> -  when substituting, whereas mytt(${ command }) and its variants do not.
> -  The latter is consistent with mytt(${|...}) from mksh but differs from
> -  bash and ksh, so in emulation modes, newlines are stripped from command
> -  output (not from tt(REPLY) assignments).
> +  when substituting, as does mytt(${ command }) when not quoted.  Placing
> +  double quotes around mytt("${ command }"), or using either mytt(${|...})
> +  format, retains newlines.  The latter is consistent with mytt(${|...})
> +  from mksh, but mytt("${ command }") differs from bash and ksh, so in
> +  emulation modes, newlines stripped even from quoted command output.
                              ^^^ typo missing "are".

To me ${ cmd; } being the non-forking version of $(...) should
behave like $(...) in that regard.

IMO, it's a bug in Bourne-like shells (and some others) that
$(...) removes *all* trailing newline characters, but removing
*one* is usually desired.

As in:

basename=$(basename -- "$file")

should remove the newline added by basename, but not the newline
characters that are found at the end of $file.

In any case, I agree ${|cmd} should expand to the value of
$REPLY as-is and trimming newlines there would not make sense.

IIRC I already mentioned it here but maybe having a:

ZSH_CMDSUBST_TRIM=<extendedglobpattern> (defaulting to $'\n##'
for backward compatibility) could address the general issue with
cmdsubst trimming too many newlines (for both $(...) and ${...;}).

One would change it to
ZSH_CMDSUBST_TRIM=$'\n' to get a saner default, or
ZSH_CMDSUBST_TRIM= to not remove anything or
ZSH_CMDSUBST_TRIM=$'(\r|)\n' or
ZSH_CMDSUBST_TRIM='[[:space:]]##' to handle MSDOS line
delimiters or remove any whitespace.

>  
>    When not enclosed in double quotes, the expansion of mytt($(command)) is
>    split on tt(IFS) into an array of words.

unless called in non-list contexts such as in scalar variable
assignment or [[ $var ]] or case $var in...

See also:

$ ./Src/zsh -c 'a=( "${(s[:])${ getconf PATH }}" ); typeset -p a'
typeset -a a=( /bin $'/usr/bin\n' )

-- 
Stephane




Messages sorted by: Reverse Date, Date, Thread, Author