Before executing a command in backticks certain preprocessing takes place:
\\becomes\(`echo \\\\`->echo \\->\)- but if there's a
\not followed by\, then\remains\(`echo \\\ `->echo \\->\) - unquoted
\at the end of the resulting command remains\(`echo \\`->echo \->\), but this is not exactly about backticks (bash -c 'echo \'->\) \"remains\"(`echo \"`->echo \"->")- but in double quotes
\"becomes"("`echo \\\"`"->echo \"->") \$becomes$(`a=1; echo \$a`->a=1; echo $a->1)\`becomes`(`echo \`echo \\\\\\\\\``->echo `echo \\\\`->\)- for a nested command substitution of level
nthe rules above applyntimes (takeecho \\\\\\\\from the previous rule, apply the first rule twice and you getecho \\, which produces\)
a.bats:
strict() { set -euo pipefail; shopt -s inherit_errexit; "$@"; }
setup() {
[ "$BATS_LIB_PATH" = /usr/lib/bats ] && BATS_LIB_PATH=$HOME/.bats/lib:$BATS_LIB_PATH
bats_load_library bats-support
bats_load_library bats-assert
strict
}
# unquoted \\ becomes \
@test "unquoted \\\\ becomes \\" {
a=`echo \\\\` # |echo \\|
assert_equal "$a" '\'
}
# unquoted \ remains \
@test "unquoted \\ remains \\" {
a=`echo \\\ ` # |echo \\ |
assert_equal "$a" '\'
}
# unquoted \ at the end of the resulting command remains \
@test "unquoted \\ at the end of the resulting command remains \\" {
a=`echo \\` # |echo \|
assert_equal "$a" '\'
}
# single-quoted \ remains \
@test "single-quoted \\ remains \\" {
a=`echo '\'` # |echo '\'|
assert_equal "$a" '\'
}
# single-quoted \\ becomes \
@test "single-quoted \\\\ becomes \\" {
a=`echo '\\'` # |echo '\'|
assert_equal "$a" '\'
}
# double-quoted \\ becomes \
@test "double-quoted \\\\ becomes \\" {
a=`echo "\\\\"` # |echo "\\"|
assert_equal "$a" '\'
}
# unquoted \" remains \"
@test "unquoted \\\" remains \\\"" {
a=`echo \"` # |echo \"|
assert_equal "$a" '"'
}
# unquoted \" inside double quotes becomes "
@test "unquoted \\\" inside double quotes becomes \"" {
a="`echo \\\"`" # |echo \"|
assert_equal "$a" '"'
}
# single-quoted \" remains \"
@test "single-quoted \\\" remains \\\"" {
a=`echo '\"'` # |echo '\"'|
assert_equal "$a" '\"'
}
# single-quoted \" inside double quotes becomes "
@test "single-quoted \\\" inside double quotes becomes \"" {
a="`echo '\"'`" # |echo '"'|
assert_equal "$a" '"'
}
# double-quoted \" remains \"
@test "double-quoted \\\" remains \\\"" {
a=`echo "\""` # |echo "\""|
assert_equal "$a" '"'
}
# double-quoted \" inside double quotes becomes "
@test "double-quoted \\\" inside double quotes becomes \"" {
a="`echo "\\\""`" # |echo "\""|
assert_equal "$a" '"'
}
# unquoted \$ becomes $
@test "unquoted \\\$ becomes \$" {
a=`a=1; echo \$a` # |echo $a|
assert_equal "$a" '1'
}
# single-quoted \$ becomes $
@test "single-quoted \\\$ becomes \$" {
a=`a=1; echo '\$a'` # |echo '$a'|
assert_equal "$a" '$a'
}
# double-quoted \$ becomes $
@test "double-quoted \\\$ becomes \$" {
a=`a=1; echo "\$a"` # |echo "$a"|
assert_equal "$a" '1'
}
# nested: unquoted \\ becomes \
@test "nested: unquoted \\\\ becomes \\" {
a=`echo \`echo \\\\\\\\\`` # |echo `echo \\\\`| -> |echo \\|
assert_equal "$a" '\'
}
# nested: unquoted \ remains \
@test "nested: unquoted \\ remains \\" {
a=`echo \`echo \\\\\\ \`` # |echo `echo \\\ `| -> |echo \\ |
assert_equal "$a" '\'
}
# nested: unquoted \ at the end of the resulting command remains \
@test "nested: unquoted \\ at the end of the resulting command remains \\" {
a=`echo \`echo \\\\\`` # |echo `echo \\`| -> |echo \|
assert_equal "$a" '\'
}
# nested: single-quoted \ remains \
@test "nested: single-quoted \\ remains \\" {
a=`echo \`echo '\'\`` # |echo `echo '\'`| -> |echo '\'|
assert_equal "$a" '\'
}
# nested: single-quoted \\ becomes \
@test "nested: single-quoted \\\\ becomes \\" {
a=`echo \`echo '\\\\'\`` # |echo `echo '\\'`| -> |echo '\'|
assert_equal "$a" '\'
}
# nested: double-quoted \\ becomes \
@test "nested: double-quoted \\\\ becomes \\" {
a=`echo \`echo "\\\\\\\\"\`` # |echo `echo "\\\\"`| -> |echo "\\"|
assert_equal "$a" '\'
}
# nested: unquoted \" remains \"
@test "nested: unquoted \\\" remains \\\"" {
a=`echo \`echo \"\`` # |echo `echo \"`| -> |echo \"|
assert_equal "$a" '"'
}
# nested: unquoted \" inside double quotes becomes "
@test "nested: unquoted \\\" inside double quotes becomes \"" {
a=`echo "\`echo \\\\\"\`"` # |echo "`echo \\\"`"| -> |echo \"|
assert_equal "$a" '"'
}
# nested: single-quoted \" remains \"
@test "nested: single-quoted \\\" remains \\\"" {
a=`echo \`echo '\"'\`` # |echo `echo '\"'`| -> |echo '\"'|
assert_equal "$a" '\"'
}
# nested: single-quoted \" inside double quotes becomes "
@test "nested: single-quoted \\\" inside double quotes becomes \"" {
a=`echo "\`echo '\"'\`"` # |echo "`echo '\"'`"| -> |echo '"'|
assert_equal "$a" '"'
}
# nested: double-quoted \" remains \"
@test "nested: double-quoted \\\" remains \\\"" {
a=`echo \`echo "\""\`` # |echo `echo "\""`| -> |echo "\""|
assert_equal "$a" '"'
}
# nested: double-quoted \" inside double quotes becomes "
@test "nested: double-quoted \\\" inside double quotes becomes \"" {
a=`echo "\`echo "\\\\\""\`"` # |echo "`echo "\\\""`"| -> |echo "\""|
assert_equal "$a" '"'
}
# nested: unquoted \$ becomes $
@test "nested: unquoted \\\$ becomes \$" {
a=`a=1; echo \`echo \\\$a\`` # |echo `echo \$a`| -> |echo $a|
assert_equal "$a" '1'
}
# nested: single-quoted \$ becomes $
@test "nested: single-quoted \\\$ becomes \$" {
a=`a=1; echo \`echo '\\\$a'\`` # |echo `echo '\$a'`| -> |echo '$a'|
assert_equal "$a" '$a'
}
# nested: double-quoted \$ becomes $
@test "nested: double-quoted \\\$ becomes \$" {
a=`a=1; echo \`echo "\\\$a"\`` # |echo `echo "\$a"`| -> |echo "$a"|
assert_equal "$a" '1'
}$ docker run --rm -itv "$PWD":/app -w /app alpine:3.21
/ # apk add git bash ncurses
/ # git clone https://github.com/bats-core/bats-core ~/.bats
/ # git clone https://github.com/bats-core/bats-support ~/.bats/lib/bats-support
/ # git clone https://github.com/bats-core/bats-assert ~/.bats/lib/bats-assert
/ # ~/.bats/bin/bats a.bats