2

In python i use:

repr('test')

for get the output:

"'test'"

I want to do the same but in the shell to be able to store this value in a variable. How can I do?

For example: If I execute a command:

echo $test

I get the output:

ghjghj "' bhj ""'' bjhv "''hjuhd

In shell I want to do this:

test=repr(repr($test))
  • 2
    Please [edit] your question and clarify what you mean. Do you just want to print a string? Save a string in a variable? Add double quotes around a string? – terdon Mar 13 '20 at 13:14
  • 2
    And what output do you expect from `test=repr(repr($test))`? Please forget python and show us what you need _in the shell_. You start with a variable `$test` whose value is `ghjghj "' bhj ""'' bjhv "''hjuhd`. OK, and what do you want from this? – terdon Mar 13 '20 at 13:24
  • if you mean `repr` as in "print all nonprintable chars as hex escapes" then `tput setaf 2 | perl -pe 's/([^[:print:]\n])/sprintf("\\x%02x", ord($1))/ge'` would print `\x1b[32m` ([source](https://superuser.com/a/895655/951886)) – milahu Apr 11 '22 at 12:18

1 Answers1

5

Something similar to Python's repr is printf %q which could be combined with printf -v which "prints" into another variable instead of stdout. (though non-standard, it's supported in the printf built-in from bash and zsh):

[prompt] foo=$(cat <<'EOT'
'"'<>\`'"'''()*@@@@$$$$````'''''
EOT
)
[prompt] printf '%q\n' "$foo"
\'\"\'\<\>\\\`\'\"\'\'\'\(\)\*@@@@\$\$\$\$\`\`\`\`\'\'\'\'\'
[prompt] printf -v bar %q "$foo"

One practical use of this is when you want to pass commands through multiple ssh (e.g. when you cannot set forwarding on intermediate hosts with ssh -J), and even one level of escaping is too much to be able to keep track of (at least for me):

[prompt] cmd='echo "$USER'\''s \$HOME on $HOSTNAME is $HOME"'
[prompt] ssh localhost "$cmd"
luser12's $HOME on kgbvax is /home/luser12
[prompt] printf -v cmd %q "$cmd"
[prompt] ssh localhost ssh localhost "$cmd"
luser12's $HOME on kgbvax is /home/luser12

[prompt] printf -v cmd %q "$cmd"
[prompt] printf -v cmd %q "$cmd"
[prompt] printf -v cmd %q "$cmd"
[prompt] echo "$cmd"
echo\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\$USER\\\\\\\\\\\\\\\'s\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\$HOME\\\\\\\\\\\\\\\ on\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\$HOSTNAME\\\\\\\\\\\\\\\ is\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\$HOME\\\\\\\\\\\\\\\"

# OK, we're ready to go

[prompt] ssh localhost ssh localhost ssh localhost ssh localhost ssh localhost "$cmd"
luser12's $HOME on kgbvax is /home/luser12

Beware however that printf %q will use the $'...' quote-escape format, which may not be supported by the remote shell (though it's supported by bash, zsh, etc and supposedly slated to be included in a future version of the POSIX standard).


Bash and ksh93 also have typeset -p (also usable as declare -p in bash), but it only works with variables, not with literals:

[prompt] typeset -p foo
declare -- foo="'\"'<>\\\`'\"'''()*@@@@\$\$\$\$\`\`\`\`'''''"
[prompt]

As an alternative to printf %q, newer versions of bash also have the ${var@Q} special expansion form:

[bash] echo "${foo@Q}"
''\''"'\''<>\`'\''"'\'''\'''\''()*@@@@$$$$````'\'''\'''\'''\'''\'''