Groovy: strings with embedded quotes don't execute as expected
This is weird: using groovy strings to hold some command lines for execution, I find that sometimes if there are quote characters inside the string, the execution simply silently fails.
WTF? (Updated, see below.)
Here's my test program:
print " 1: " ; "grep nameserver /etc/resolv.conf".execute().text.eachLine {println it } ; println ""
print " 2: " ; "grep 'nameserver' /etc/resolv.conf".execute().text.eachLine {println it } ; println ""
print " 3: " ; """grep nameserver /etc/resolv.conf""".execute().text.eachLine {println it } ; println ""
print " 4: " ; """grep "nameserver" /etc/resolv.conf""".execute().text.eachLine {println it } ; println ""
print " 5: " ; """grep 'nameserver' /etc/resolv.conf""".execute().text.eachLine {println it } ; println ""
print " 6: " ; "awk /nameserver/ /etc/resolv.conf".execute().text.eachLine{ println it } ; println ""
print " 7: " ; "awk '/nameserver/' /etc/resolv.conf".execute().text.eachLine{ println it } ; println ""
print " 8: " ; """awk "/nameserver/" /etc开发者_如何转开发/resolv.conf""".execute().text.eachLine{ println it } ; println ""
print " 9: " ; """awk '/nameserver/' /etc/resolv.conf""".execute().text.eachLine{ println it } ; println ""
print "10: " ; """awk "/nameserver/{print \$2}" /etc/resolv.conf""".execute().text.eachLine{ println it } ; println ""
return
Here's the results:
$ groovy weird.groovy
1: nameserver 10.3.0.101
nameserver 10.4.1.237
nameserver 10.2.1.34
2:
3: nameserver 10.3.0.101
nameserver 10.4.1.237
nameserver 10.2.1.34
4:
5:
6: nameserver 10.3.0.101
nameserver 10.4.1.237
nameserver 10.2.1.34
7:
8: nameserver 10.3.0.101
nameserver 10.4.1.237
nameserver 10.2.1.34
domain lnx.copansys.com
search lnx.copansys.com tst.copansys.com copansys.com
9:
10:
Update
Here's another example:
"bash -c echo Hello".execute().text.eachLine{ println it }
"bash -c echo 'Hello'".execute().text.eachLine{ println it }
"bash -c echo \'Hello\'".execute().text.eachLine{ println it }
Results:
groovy> "bash -c echo Hello".execute().text.eachLine{ println it }
groovy> "bash -c echo 'Hello'".execute().text.eachLine{ println it }
groovy> "bash -c echo \'Hello\'".execute().text.eachLine{ println it }
'Hello!'
Observe that embedding a backslash-quoted ' doesn't seem to help.
When you execute commands with String.execute()
, they don't get parsed by a command shell. The quotes are passed through to the actual commands executed; in this case, grep and awk.
This is illustrated by replacing grep and awk with echo:
print " 1: " ; "echo something".execute().text.eachLine {println it } ; println ""
print " 2: " ; "echo 'something'".execute().text.eachLine {println it } ; println ""
print " 3: " ; """echo something""".execute().text.eachLine {println it } ; println ""
print " 4: " ; """echo "something" """.execute().text.eachLine {println it } ; println ""
print " 5: " ; """echo 'something'""".execute().text.eachLine {println it } ; println ""
Which results in:
1: something
2: 'something'
3: something
4: "something"
5: 'something'
A simple workaround is to build the command line as a list of strings:
["awk", 'BEGIN { print "hello" }'].execute().text
If you need finer control over the how the command is parsed, take a look at ProcessBuilder
, the Java class String.execute()
is built around.
http://docs.groovy-lang.org/latest/html/documentation/index.html#all-strings
It seems that the python style quoting ie "'"
('
) and """""""
("
) you expect doesn't exist in groovy so '
or "
in strings literals must be written as \'
and \"
精彩评论