简体   繁体   中英

How can I do ANSI C quoting of an existing bash variable?

I have looked at this question , but it does not cover my use case.

Suppose I have the variable foo which holds the four-character literal \\x60 .

I want to perform ANSI C Quoting on the contents of this variable and store it into another variable bar .

I tried the following, but none of them achieved the desired effect.

bar=$'$foo'   
echo $bar     
bar=$"$foo"     
echo $bar       

Output:

$foo
\x61

Desired output (actual value of \\x61 ):

a

How might I achieve this in the general case, including non-printable characters? Note that in this case a was used just as an example to make it easier to test whether the method worked.

By far the simplest solution, if you are using bash :

printf %b "$foo"

Or, to save it in another variable name bar :

printf -v bar %b "$foo"

From help printf :

In addition to the standard format specifications described in printf(1) and printf(3), printf interprets:

  %b expand backslash escape sequences in the corresponding argument %q quote the argument in a way that can be reused as shell input %(fmt)T output the date-time string resulting from using FMT as a format string for strftime(3) 

There are edge cases, though:

\\c terminates output, backslashes in \\', \\", and \\? are not removed, and octal escapes beginning with \\0 may contain up to four digits

The best method I know is

  y=$(printf $(echo "$foo"|sed 's/%/%%/g'))

As mentioned in the comments, this trims trailing newlines from $foo . To overcome this:

moo=$(echo "${foo}:end"|sed 's/%/%%/g')
moo=$(printf "$moo")
moo=${moo%:end}
# the escaped string is in $moo
echo "+++${moo}---"

I just found out that I can do this. Edited based on comments.

bar=$( echo -ne "$foo" )

The following works:

 eval bar=\$\'$x\'

The command bar=$'\\x61' has to be constructed first, then eval evaluates the newly built command.

Sample of conversion via shell. Problem, the code is octal using \\0nnn and hexdecimal (not on all shell) using \\xnn (where n are [hexa]digit)

foo="\65"
print "$( echo "$foo" | sed 's/\\/&0/' )"

5

with awk, you could certainly convert it directly

Since bash 4.4 there is a variable expansion to do exactly that:

$ foo='\x61';     echo "$foo" "${foo@E}"
\x61 a

To set another variable use:

$ printf -v bar "${foo@E}";     echo "$bar"
a

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM