[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: How does quote removal work with alternative forms of parameter expa
From: |
Koichi Murase |
Subject: |
Re: How does quote removal work with alternative forms of parameter expansion? |
Date: |
Mon, 27 May 2024 11:03:59 +0900 |
2024年5月27日(月) 9:38 Philippe Cerfon <philcerf@gmail.com>:
> Just out of curiosity:
> Is there any place in the POSIX text from where I could have deduced
> that behavior?
Lawrence seems to have already explained it nicely in a reply:
[1] https://lists.gnu.org/archive/html/help-bash/2024-05/msg00092.html
> > > So it seems as if there'd be first a "normal" quote removal on the
> > > word part of these parameter expansion forms and then the outer quote
> > > removal, right?
> >
> > Yes.
>
> And we're still taking about only the # ## % and %% forms here, right?
Ah, yes, that part was quoted from the part you discussed ${var#...},
etc. Sorry for the confusing quoting.
> Why does:
> $ bar='1 2'
> $ printf '%s\n' "${unset_var:-"$bar"}"
>
> then result in:
> 1 2
> and not:
> 1
> 2
>
> ?
> If the above would be like ""$bar"" I'd have thought the $bar is not
> quoted and thus produces separate files?
It's still "something like" x=""$bar"", and not exactly equivalent to
directly writing «printf ""$bar""». Just the processing of quoting and
expansions are affected by the inside double quotes. I think you can
regard «"» as a special character to toggle the behavior in this
context.
> Is this coupling then also POSIX behaviour?
POSIX specifies it to be unspecified as Lawrence has explained [1].
> Is there even a way, when using the + - = ? forms, to use quoting in
> the word part and still be portable?
> It would seem to me that backslash quoting is then the only portable way?
>
> [...]
>
> I guess I do (kind of) understand now how it's done in bash, but which
> rules should one follow if one tries to program portable?
There are even more cases that one needs to be careful about the
quoting nested in the double-quoted parameter expansions: `shopt -s
patsub_replacement' and `shopt -s compat42' in addition to the
mentioned `shopt -s extquote'. I wrote some points about
`patsub_replacement' and `compat42' in [2] before, (though it doesn't
cover the present case).
[2]
https://github.com/scop/bash-completion/blob/main/doc/styleguide.md#patsub_replacement-for-array-elements
My conclusion is that we shouldn't double-quote parameter expansions
when any inside quoting is involved. I always assign a result to a
variable with no double-quoting and use it in the command. I would
write your example as
foo() {
local error1_format_string=${5:-'some default string with backticks `%s`'}
printf "$error1_format_string" "$foo"
}
The right-hand side (RHS) of variable assignments is not subject to
word splitting and pathname expansions, so one usually doesn't need to
quote the parameter expansions.
When I want to include shell special characters such as
[~[:space:]<>&|;\"`'] in the right-hand side, I quote them separately
as
local string='~/a b c '${5:-'something `%s`'}'<>&|;\"`'\'' x y z'
This is also nice with text editors highlighting the entire "..." as
the single literal and not highlighting the inside structures (though
we can say such a text editor could be improved).
When I want to specify it as an argument to another command (instead
of RHS of assignments), I'd assign it in a variable and then specify
"$var" to the command: For example, instead of «printf '%s\n'
"${x:-'$bar'}"», I'd write
local v=${x:-'$bar'} # if you want the literal '$bar'
printf '%s\n' "$v"
The remaining case is that the nested quotation in the array
assignments of the form arr2=("${arr1[@]...}"). The elements of array
assignments are still subject to word splitting and pathname
expansions, so one cannot simply omit the outside double quotes. In
this case, I don't know a good solution so would recommend people to
first perform the simple assignments, and then modify the elements one
by one:
local arr2 key
arr2=("${arr1[@]}")
for key in "${!arr2[@]}"; do
arr2[$key]=${arr2[$key]...}
done
This is also mentioned in [2].
> > Another case you might be interested in is
> >
> > x="${1:-"foo \bar"foo\ bar"foo\ bar"}"
>
> What especially do you mean here?
Sorry, as I've already mentioned in [3] that was just a leftover of
editing my reply.
[3] https://lists.gnu.org/archive/html/help-bash/2024-05/msg00094.html
--
Koichi
- Re: How does quote removal work with alternative forms of parameter expansion?, (continued)
- Re: How does quote removal work with alternative forms of parameter expansion?, Lawrence Velázquez, 2024/05/26
- Re: How does quote removal work with alternative forms of parameter expansion?, Philippe Cerfon, 2024/05/26
- Re: How does quote removal work with alternative forms of parameter expansion?, Lawrence Velázquez, 2024/05/26
- Re: How does quote removal work with alternative forms of parameter expansion?, Philippe Cerfon, 2024/05/26
- Re: How does quote removal work with alternative forms of parameter expansion?, Lawrence Velázquez, 2024/05/26
- Re: How does quote removal work with alternative forms of parameter expansion?, Chet Ramey, 2024/05/29
Re: How does quote removal work with alternative forms of parameter expansion?, Koichi Murase, 2024/05/26