Why does $'\141' convert to ASCII 'a' as expected, but constructing the same string doesn't convert?

78 Views Asked by At
#!/bin/bash
$'\141'

string1="$'\\"
number=141
string2="'"
result="${string1}${number}${string2}"
$result

Running this script gives this response:

./temp.sh: line 2: a: command not found
./temp.sh: line 8: $'\141': command not found

Why are these two not equivalent? What would need to be changed in the second attempt to get the correct ASCII conversion?

Clearly the second try isn't being converted to 'a' as expected. Why is this? I thought maybe because I escaped the special meaning of backslash by doing \\. But if that's the case, does it mean it's not possible to do this ASCII conversion on a constructed string?

For additional information, this is for a CTF where I must run cat ../../flag or equivalent without using any letters. So I'm trying to use an ASCII conversion.

2

There are 2 best solutions below

1
Gilles Quénot On

If you have error, it's simply a syntax error.

What you need to construct ASCII letters from variables:

i=141; printf '%b\n' '\'$i
a

or to construct from multiple variables (only 2 needed):

start='\' number=141; printf '%b\n' "$start$number"
a

From POSIX Open Group:

The %b conversion specification is not part of the ISO C standard; it has been added here as a portable way to process -escapes expanded in string operands as provided by the echo utility. See also the APPLICATION USAGE section of echo for ways to use printf as a replacement for all of the traditional versions of the echo utility.

See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html

1
jhnc On

From the Bash Reference Manual:

3.1.2.2 Single Quotes

Enclosing characters in single quotes (') preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

3.1.2.3 Double Quotes

Enclosing characters in double quotes (") preserves the literal value of all characters within the quotes, with the exception of $, `, \, [...]. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or newline. Within double quotes, backslashes that are followed by one of these characters are removed. Backslashes preceding characters without a special meaning are left unmodified. [...]

3.1.2.4 ANSI-C Quoting

Character sequences of the form $’string’ are treated as a special kind of single quotes. The sequence expands to string, with backslash-escaped characters in string replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded [...]

The expanded result is single-quoted, as if the dollar sign had not been present.

Emphasis mine.

Note that the backslash escape sequences allowed in ANSI-C quoting are not defined in double-quoted strings. As described in 3.1.2.3, backslashes in double-quoted strings have a different use/meaning.