I am attempting to write a simple bash parser. I am following the steps in this wiki. One of the assumptions I make is that I can do a pass over the entire input string and remove all single and double quotes if I escape the characters correctly. When run in the bash, they two strings should yield the same output.
This section of my parser takes any given string and removes single and double quotes from it (except quotes that are escaped and interpreted as literals). Both strings should still yield the same result when executed in bash.
My parser converts the original to My Parse like below. However, the original works, but My Parse does not.
# Original
$ node -p "console.log($(echo \"hello world\"))"
hello world
My Parse: Escape everything within double quotes except command substitution
v v
$ node -p \c\o\n\s\o\l\e.\l\o\g($(echo "hello world"))
[eval]:1
console.log("hello
^^^^^^
SyntaxError: Invalid or unexpected token
I have several ideas about why my parsing is wrong.
I am not understanding some fundamental aspect of how command substitution inside double quotes works. My understanding is command substitution occurs first, then quotes are processed.
I am not understanding some fundamental aspect of how command substitution is actually output. My understanding is
$(echo \"hello world\")
should yield a string"hello world"
not commands"hello
andworld"
There is some special-ness with the
echo
command (potentially because it is variadic). I am actually getting lucky that this works in the original scenario, but actually, changing the command inside the command substitution could break it...There is a problem with my node / javascript problem. This is pretty simple js, so I don't think this is it...
One last interesting thing: It works when I wrap the command substitution in double quotes. Maybe to ask this whole question differently, how could I write the same input as below without the double quotes (excluding the escaped ones).
# Escape everything but keep command substitution in double quotes
v v
$ node -p \c\o\n\s\o\l\e\.\l\o\g\("$(echo \"hello world\")"\)
hello world
Note: This question is somewhat a follow up to this question about escaping double quotes
$(cmd)
command substitution is not simple, it needs a recursive parser to do it right. Most shells do it wrong, evenbash
fails to do it right some cases. Currentlybosh
is the only shell with no known bug in parsing command substitutions. So do not believe that this is a simple task to implement... – schily Sep 17 '20 at 22:53bosh
, thank you :) – falky Sep 17 '20 at 23:05name.c
inside the functionmatch_cmd()
. This calls a recursiv parser that stops at the first supefluous)
. BTW: the parser itself is in the functioncmd()
. The binary syntax tree that is the result from calling the parser is then converted back into text and used as the next "word" from the input. The execution of the code later happens in the filemacro.c
. – schily Sep 18 '20 at 10:31