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}"
''\''"'\''<>\`'\''"'\'''\'''\''()*@@@@$$$$````'\'''\'''\'''\'''\'''
test=repr(repr($test))
? Please forget python and show us what you need in the shell. You start with a variable$test
whose value isghjghj "' bhj ""'' bjhv "''hjuhd
. OK, and what do you want from this? – terdon Mar 13 '20 at 13:24repr
as in "print all nonprintable chars as hex escapes" thentput 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