Comparison of Escape class and String.shell escape
From WhyNotWiki
[edit] Comparison of Escape class and String#shell_escape
Recall that if exec/system "is given a single argument, that argument is taken as a line that is subject to shell expansion before being executed. If multiple arguments are given, the second and subsequent arguments are passed as parameters to command with no shell expansion." (exec)
exec "echo *" # echoes list of files in current directory exec "echo", "*" # echoes an asterisk
Escape class |
String#shell_escape (Facets) |
|
|---|---|---|
| Test: Given a string A of "special characters" as input, can the escaper produce a string that, when fed to a console app, will that program see the original string A exactly as it was input? | ||
| generated string |
irb -> Escape.shell_command([ "echo", %q{!&'"`$0 |()<>} ])
=> "echo '!&'\\''\"`$0 |()<>'"
|
irb -> "echo " + %q{!&'"`$0 |()<>}.shell_escape
=> "echo !\\&\\'\\\"\\`$0\\ \\|\\(\\)\\<\\>"
|
| results of executing |
irb -> system Escape.shell_command([ "echo", %q{!&'"`$0 |()<>} ])
!&'"`$0 |()<>
Correct! |
irb -> system("echo " + %q{!&'"`$0 |()<>}.shell_escape)
!&'"`sh |()<>
Incorrect!
irb -> system("echo '" + %q{!&'"`$0 |()<>}.shell_escape + "'")
irb -> system("echo '" + %q{'}.shell_escape + "'")
sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file
Incorrect!
irb -> system('echo "' + %q{!&'"`$0 |()<>}.shell_escape + '"')
!\&\'"`sh\ \|\(\)\<\>
irb -> system("echo", %q{!&'"`$0 |()<>}.shell_escape)
!\&\'\"\`$0\ \|\(\)\<\>
Incorrect! Introduced unwanted |
| Question: | ||
|
It looks like Escape.shell_command expects its output to be expanded by the shell. (
irb -> system Escape.shell_command([ "echo", %q{!&'"`$0 |()<>} ])
!&'"`$0 |()<>
Correct! But not so much this:
irb -> system("echo", Escape.shell_command(%q{!&'"`$0 |()<>}))
'!&'\''"`$0 |()<>'
Incorrect! |
Unlike with "So how am I supposed to use .shell_escape??" |
|
|
Test: Given as input 3 args, some of which contain spaces, the escaper produce a string that, when fed to a console app, will that program see exactly 3 args (rather than, say, > 3)? |
||
| generated string |
irb -> Escape.shell_command(["./show_args.rb", 'arg1', 'multiple words for single argument', 'arg3'])
=> "./show_args.rb arg1 'multiple words for single argument' arg3"
|
irb -> ["./show_args.rb", 'arg1', 'multiple words for single argument'.shell_escape, 'arg3'].join(' ')
=> "./show_args.rb arg1 multiple\\ words\\ for\\ single\\ argument arg3"
|
| results of executing |
irb -> system Escape.shell_command(["./show_args.rb", 'arg1', 'multiple words for single argument', 'arg3']) ["arg1", "multiple words for single argument", "arg3"] arg1 multiple words for single argument arg3 Correct! |
system ["./show_args.rb", 'arg1', 'multiple words for single argument'.shell_escape, 'arg3'].join(' ')
["arg1", "multiple words for single argument", "arg3"]
arg1
multiple words for single argument
arg3
Correct! |
| generated string |
irb -> Escape.shell_command(["./show_args.rb", 'arg1', %q{'an arg that's got "quotes"}, 'arg3'])
=> "./show_args.rb arg1 \\''an arg that'\\''s got \"quotes\"' arg3"
|
irb -> ["./show_args.rb", 'arg1', %q{an arg that's 'got' "quotes"}.shell_escape, 'arg3'].join(' ')
=> "./show_args.rb arg1 an\\ arg\\ that\\'s\\ \\'got\\'\\ \\\"quotes\\\" arg3"
|
| results of executing |
irb -> system Escape.shell_command(["./show_args.rb", 'arg1', %q{'an arg that's got "quotes"}, 'arg3'])
["arg1", "'an arg that's got \"quotes\"", "arg3"]
arg1
'an arg that's got "quotes"
arg3
Correct! |
irb -> system ["./show_args.rb", 'arg1', %q{an arg that's 'got' "quotes"}.shell_escape, 'arg3'].join(' ')
["arg1", "an arg that's 'got' \"quotes\"", "arg3"]
arg1
an arg that's 'got' "quotes"
arg3
Correct! |
| pros |
|
|
| cons |
|
|
|
Rules / Notes |
||
|
||
| conclusion | winner | |
> cat show_args.rb #!/usr/bin/ruby p ARGV puts ARGV
Ruby libraries edit (Category edit)
