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) – 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\\\\\\\\ \\\\\\\&quot;\\\\\\\$USER\\\\\\\'s\\\\\\\\ \\\\\\\\\\\\\\\$HOME\\\\\\\\ on\\\\\\\\ \\\\\\\$HOSTNAME\\\\\\\\ is\\\\\\\\ \\\\\\\$HOME\\\\\\\&quot;

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}"
''\''"'\''<>\`'\''"'\'''\'''\''()*@@@@$$$$````'\'''\'''\'''\'''\'''