Home > Software design >  How can `printf %q` be reversed in a shell?
How can `printf %q` be reversed in a shell?

Time:11-16

The command printf %q (from GNU coreutils or bash) can be used to quote an array of arguments including whitespaces, newlines and quotes. For example:

$ main() { printf '%q ' "${@}"; } && main "'a'" '"b"' 'c d' $'e\nf'
\'a\' \"b\" c\ d $'e\nf' 

Is it possible to reverse this operation, i.e. create an argument array from a string created by printf %q

  1. In a POSIX shell?
  2. In Bash?
  3. Using additional tools?

Insights:

  • xargs does not handle quoted newlines.
  • zsh can do this for a string stored in variable args: "${(Q@)${(z)args}}"

CodePudding user response:

main() { printf '%q ' "${@}"; }
str=$(main "'a'" '"b"' 'c d' $'e\nf')

It's really simple. Use the following to re-set positional arguments:

eval "set $str"

CodePudding user response:

use declare:

quoted=$(main  "'a'" '"b"' 'c d' $'e\nf')
declare -a "myvar=($quoted)"
declare -p myvar

outputs

declare -a myvar=([0]="'a'" [1]="\"b\"" [2]="c d" [3]=$'e\nf')

This can't be used to evaluate commands:

$ declare -a "myvar=($(main  ls -l sensitive files))"
$ declare -p myvar
declare -a myvar=([0]="ls" [1]="-l" [2]="sensitive" [3]="files")

One thing to note: if you use declare in a function, the variable becomes local to that function (unless you use declare -g in which case it's global)

  • Related