Reputation: 15
I am wondering how can I execute ruby code without saving a file. For example:
ruby -e 'Time.now'
However, the quotes are a problem, for example:
ruby -e 'puts 'A syntax error''
I could use doble quotes instead:
ruby -e 'puts "No error"'
Or:
ruby -e "puts 'No error'"
The issue is that I am running arbitrary code inside a container so I can't avoid the issue with a manual replacement and scaping the quotes also generates an error:
ruby -e 'puts \'A syntax error\''
So I wonder how can I execute ruby code without files and without worrying about quotes inside the code.
Upvotes: 1
Views: 240
Reputation: 16905
You can use a Shell HEREDOC. The exact syntax may differ between shells but in BASH it is:
Edit: All Shells have the same syntax and behave the same way (see IEEE standard quote below).
ruby <<'EOS'
$error = 'A syntax error'
puts $error
EOS
Note: The quotes of <<'EOS'
prevent the Shell from expanding variables inside the HEREDOC, or else $error
would be expanded before being passed to Ruby. Also, you can use whatever word you prefer instead of EOS
, for ex:
ruby <<'end of ruby script'
puts 'example'
end of ruby script
The IEEE standard says:
2.7.4 Here-Document
The redirection operators
<<
and<<-
both allow redirection of lines contained in a shell input file, known as a "here-document", to the input of a command.The here-document shall be treated as a single word that begins after the next
<newline>
and continues until there is a line containing only the delimiter and a<newline>
, with no<blank>
s in between. Then the next here-document starts, if there is one. The format is as follows:[n]<<word here-document delimiter
where the optional n represents the file descriptor number. If the number is omitted, the here-document refers to standard input (file descriptor 0).
If any character in word is quoted, the delimiter shall be formed by performing quote removal on word, and the here-document lines shall not be expanded. Otherwise, the delimiter shall be the word itself.
If no characters in word are quoted, all lines of the here-document shall be expanded for parameter expansion, command substitution, and arithmetic expansion. In this case, the backslash in the input behaves as the backslash inside double-quotes (see Double-Quotes). However, the double-quote character (
'"'
) shall not be treated specially within a here-document, except when the double-quote appears within$()
,``
, or${}
.If the redirection symbol is
<<-
, all leading<tab>
s shall be stripped from input lines and the line containing the trailing delimiter
That said, it's impossible to completely prevent conflicts. For example this Ruby code would break your Shell script:
ruby <<'EOS'
puts <<-EOS
example
EOS
EOS
The only way to work around that is to use a word that is very unlikely to appear in the Ruby code, for example:
ruby <<'2eGRng8B6NEmNphkA2K4yc9Y782PQZpWzkUW7pwGdmybuMBG5 PVtkzZkeSKGLq4'
puts <<-EOS
example
EOS
2eGRng8B6NEmNphkA2K4yc9Y782PQZpWzkUW7pwGdmybuMBG5 PVtkzZkeSKGLq4
Upvotes: 3
Reputation: 12347
You have to escape the quotes properly, for example:
ruby -e 'puts '\''foo bar'\''; puts '\''foo bar'\''; '
# ^-----^
# quote this
# ^-------^
# quote that
# ^^
# escaped quote to pass to Ruby
Output:
foo bar
foo bar
Note that most quotes are needed to simply quote the Ruby code in the shell. The escaped quote \'
is an actual quote that is passed to Ruby.
Upvotes: 2
Reputation: 84343
To avoid (or at least simplify) the issue of quoting String objects inside shell quotes, you can use a heredoc or a percent-string such as %q
for single quotes or %Q
for double-quotes. For example:
# double-quoted percent string
ruby -e 'puts %Q(No error.)'
# single-quoted percent string
ruby -e 'puts %q(A syntax error.)'
# quoted String with nested symbols
ruby -e 'puts %Q[You can use most [percent-literal] symbols safely.]'
Note that you can use almost any paired or unnpaired symbol character to open and close the percent literal. ()
, []
, and {}
are common choices, but anything other than single quotes and \'
should be safe from the shell inside a single-quoted argument to -e
.
Upvotes: 1