According to the bash documentation on expansions:
The basic form of Parameter Expansion is ${parameter}
. The value of Parameter is substituted. The Parameter is a shell Parameter as described above (see Shell Parameters) or an array Reference (see Arrays).
That is, the parameter that is passed to the expansion must be a shell Parameter. And if we check the respective documentation, there is described that this parameter must be a variable, a positional parameter (as $1
, $2
, etc), or one of the special parameters (like the $@
and the $#
, for example).
But when trying to make an expansion within the other (as for example ${${variavel//-/_},,}
), the result of the first (the innermost) is any text, which is not a valid parameter, and so the external expansion fails.
Therefore, an alternative to doing everything in a single line would be to do just one of the expansions, and treat the other with some other command. In your case, it could be one of the options below:
echo ${variavel//-/_} | tr '[:upper:]' '[:lower:]'
echo ${variavel,,} | sed s/-/_/g
Other options for bash can be consulted here and here (I haven’t tested them all).
And another alternative, if possible, is to change shell. zsh, for example, supports nested expansions.
I believe two expansions aren’t possible, but maybe they’re nested, something like
echo ${${variavel//-/_},,}
. Have you tried something like this?– Woss
@Woss, I think an invalid construction, but it doesn’t hurt to try...
– Jefferson Quesado
bash: ${${variavel//-/_},,}: bad substitution
=(– Jefferson Quesado
In ZSH I managed to make a similar construction;
echo ${${variavel//a/T}//-/_}
resulted inTBcDe__FG
, but the,,
also gave the bad substitution.– Woss
Yeah, but I’m stuck at Bourne Again... at least I can access the position
[0]
and do thedowncase
... as if the positional expansion did not interfere with other expansions– Jefferson Quesado
From what I’ve been doing, bash can’t seem to stand nested expansions. Then one way to do it on a single line would be to use one of the expansions and replace the second with some other command:
echo ${variavel//-/_} | tr '[:upper:]' '[:lower:]'
orecho ${variavel,,} | sed s/-/_/g
– hkotsubo
@hkotsubo Put life. As unpleasant as it is to me, it is still an answer. Anyway, invoking two expansions seems cheaper than making a pipeline and invoking an executable (
echo
usually is the built-in, hardly the executable/bin/echo
, when at the level of shell script, so I’m not counting it)– Jefferson Quesado
Well, I put an answer (I was just looking for references in the documentation). Even if it is not the most pleasant solution, it is there as an option :-)
– hkotsubo