Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash: How to use operator parameter expansion ${parameter@operator}?

I've googled and tried so many things and never could get anything to work with ${parameter@operator}. All I find is more links to the same documentation. So I think a proper answer with practical examples would be very helpful to its understanding.

The documentation says:

${parameter@operator}

The expansion is either a transformation of the value of parameter or information about parameter itself, depending on the value of operator. Each operator is a single letter:

Q
The expansion is a string that is the value of parameter quoted in a format that can be reused as input.

It also says about quoting:

3.1.2 Quoting
Quoting is used to remove the special meaning of certain characters or words to the shell.

So my reasoning is that the output of this (special character $):

a="To be reused as an input string, \$0 needs to be quoted"
echo ${a@Q}

should be this (between "", the '\' is removed, so needs quoting again to be used as an input):

To be reused as an input string, \$0 needs to be quoted

but I get:

bash: ${a@Q}: bad substitution

I tried different combinations of:

${a@q}, "${a@Q}", a='To be reused as an input string, $0 needs to be quoted'

to no avail.

Actually, any operators I try to use always yields the bad substitution error. Those seems to be very obscure features of bash. I've omitted from this post about half an hour of attempts each one more twisted than the previous!

like image 679
Fireplume Avatar asked Nov 22 '16 01:11

Fireplume


People also ask

What is parameter expansion in Bash?

3 years ago. The parameter is used in bash to store data. Different types of data can be stored in the parameter, such as integer, string, array, etc. by using built-in declare keyword.

What does * mean when writing a parameter expansion?

If parameter is ' * ' or ' @ ', the value substituted is the number of positional parameters. If parameter is an array name subscripted by ' * ' or ' @ ', the value substituted is the number of elements in the array.

How do you expand a variable in Bash?

If the first character of "PARAMETER" is an exclamation point, Bash uses the value of the variable formed from the rest of "PARAMETER" as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of "PARAMETER" itself.

What does $# mean in Bash script?

$# is the number of positional parameters passed to the script, shell, or shell function. This is because, while a shell function is running, the positional parameters are temporarily replaced with the arguments to the function. This lets functions accept and use their own positional parameters.


2 Answers

For those who arrive here looking for information on a different expansion operator, here's a quick list of the available expansion characters and their effects.

${varname@Q} returns a single-Quoted string with any special characters (such as \n, \t, etc.) escaped.

Examples:

$ foo="one\ntwo\n\tlast"
$ echo "$foo"
one\ntwo\n\tlast

$ echo ${foo@Q}
'one\ntwo\n\tlast'

${varname@E} returns a string with all the escaped characters Expanded (e.g. \n -> newline).

Examples:

$ foo="one\ntwo\n\tlast"
$ echo "${foo}"
one\ntwo\n\tlast

$ echo "${foo@E}"
one
two
        last

${varname@P} returns a string that shows what the variable would look like if it were used as a Prompt variable (i.e. PS1, PS2, PS3)

Example:

$ bar='host: \h'
$ echo ${bar@P}
host: myhost1

(There are many more escape sequences that can be applied in prompt variables. See the bash documentation.)

${varname@A} returns a string that can be used to Assign the variable with its existing name, value, and declare options if any.

Example:

$ foo="test1"
$ echo ${foo@A}
foo='test1'

$ declare -i foo=10
$ echo "${foo@A}"
declare -i foo='10'

${varname@a} returns a string listing the Atributes of the variable.

Example:

$ declare -ir foo=10
$ echo ${foo@a}
ir

(The available declare options are: -r readonly, -i integer, -a array, -f function, -x exportable.)

like image 140
RichTBreak Avatar answered Nov 11 '22 17:11

RichTBreak


Sorry, I didn't browse Stack properly, there is an example use here:

How to display a file with multiple lines as a single string with escape chars (\n)

$ foo=$(<file.txt)
$ echo "${foo@Q}"
$'line1\nline2'

Plus, I don't have bash 4.4 in which the feature was implemented < sigh >

like image 20
Fireplume Avatar answered Nov 11 '22 16:11

Fireplume