I needed to know what was in my Ruby load path, so I did this:
$ ruby -e "puts $LOAD_PATH"
It didn't print anything out, which I didn't expect. So I tried this:
$ ruby -e "puts $:"
/usr/local/lib/site_ruby/1.8
/usr/local/lib/site_ruby/1.8/i486-linux
/usr/local/lib/site_ruby/1.8/i386-linux
/usr/local/lib/site_ruby
/usr/lib/ruby/vendor_ruby/1.8
/usr/lib/ruby/vendor_ruby/1.8/i486-linux
/usr/lib/ruby/vendor_ruby
/usr/lib/ruby/1.8
/usr/lib/ruby/1.8/i486-linux
/usr/lib/ruby/1.8/i386-linux
.
Why does the second one give me the expected output and the first one doesn't? Shouldn't they be the same? I just tried it in irb, and I got the results I expected.
This is my Ruby version, in case it makes a difference:
$ ruby --version
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
They are not. Try running this command:
$ ruby -e 'puts $LOAD_PATH'
which doesn't make shell expand $LOAD_PATH due to use of ' instead of ".
Related
My question is similar to this one: How to detect if my shell script is running through a pipe?. The difference is that the script I’m working on is written in Ruby.
Let’s say I run:
./test.rb
I expect text on stdout with color, but
./test.rb | cat
I expect the color codes to be stripped out.
Use $stdout.isatty or more idiomatically, $stdout.tty?. I created a little test.rb file to demonstrate, contents:
puts $stdout.isatty
Results:
$ ruby test.rb
true
$ ruby test.rb | cat
false
Reference: https://ruby-doc.org/core/IO.html#method-i-isatty
Use IO#stat.pipe?.
IO#tty? returns true only on a TTY device.
Returns false for UNIX-style pipes (see "man 2 pipe").
$ echo "something" | ruby -e 'puts $stdin.stat.pipe?'
true
$ echo "something" | ruby -e 'puts $stdin.tty?'
false
$ ruby -e 'puts $stdin.tty?'
true
Consider oneliner
$ ruby -e 'puts 1 + 1'
which uses ruby as a command-line calculator. I would like to write the expression without puts. Is there a switch for it in ruby command?
It is impossible with ruby command line switches, but it’s easily achievable with shell:
⮀ cat /usr/local/bin/rubyoneliner
#!/bin/sh
ruby -e "puts $#"
⮀ rubyoneliner '1 + 1'
2
or with bash/zsh function.
There is no way to have an implicit print in ruby. However, you can shrink your oneliner a little more -> replacing puts by p and including the require in the shell command :
$ ruby -rsy -e 'p 42.kWh.in :MJ'
-rsy whould replace the require 'sy'.
Otherwise you can use the fact that the option -p, implicitely puts the $_ variable with something like (much longer however) :
$ printf whatever | ruby -rsy -pe '$_ = 42.kWh.in :MJ'
or uglier
$ printf whatever | ruby -rsy -pe 'sub("whatever", 42.kWh.in :MJ)'
I'm using uname -n as an example. I've tried other shell commands, using the full pathname to the shell command, and I used other delimiters, such as %x( ) and %x[ ].
$ uname -n
my-server
$ which env
/usr/bin/env
$ which ruby
/home/ubuntu/.rvm/rubies/ruby-2.2.1/bin/ruby
$ irb
2.2.1 :001 > %x{uname -n}
=> "my-server\n"
2.2.1 :002 > exit
$ cat ET.rb
#!/usr/bin/env ruby
%x{uname -n}
$ ruby ET.rb
$ ### !!!?!?!? I'm expecting "my-server"
In IRB, it will show the results of any Ruby statements you feed it. But if in a Ruby script, you should use puts or print method to print something out:
puts %x{uname -n}
or:
print %x{uname -n}
I have a ruby bin I'd like to pass information to in this fashion:
some_text | ./bin/my_ruby_bin
where some_text will be accessible by ARGV
is this possible with ruby + shell or am I taking the wrong approach here?
Here is simple solution that works for my cause, but it appears there are many ways to do this:
# ./bin/my_ruby_bin
#!/usr/bin/env ruby -n
puts "hello: #{$_}"
notice the -n flag
from command line:
echo 'world' | ./bin/my_ruby_bin
# => hello world
More on ruby -n
ruby -h
-n assume 'while gets(); ... end' loop around your script
When using RBConfig to determine my ruby version, I get the "wrong" teeny version when using ruby 1.9.3:
# ruby -v
ruby 1.9.3p286 (2012-10-12 revision 37165) [i686-linux]
# ruby -rrbconfig -e 'puts RbConfig::CONFIG.fetch(%q(MAJOR))'
1
# ruby -rrbconfig -e 'puts RbConfig::CONFIG.fetch(%q(MINOR))'
9
# ruby -rrbconfig -e 'puts RbConfig::CONFIG.fetch(%q(TEENY))'
1
Using Ruby 1.8.7 - this works fine:
$ ruby -v
ruby 1.8.7 (2012-06-29 patchlevel 370) [x86_64-linux]
$ ruby -rrbconfig -e 'puts Config::CONFIG.fetch(%q(MAJOR))'
1
$ ruby -rrbconfig -e 'puts Config::CONFIG.fetch(%q(MINOR))'
8
$ ruby -rrbconfig -e 'puts Config::CONFIG.fetch(%q(TEENY))'
7
I know I can get patchlevel and use that a bit, but why is ruby 1.9.3 returning 1 as its teeny version?
Ruby has two concepts of version: The actual release version, and the "compatibility version". For all Rubies 1.9.1 -> 1.9.3, the compatibility version is 1.9.1, because they are all backward compatible with the 1.9.1 release.
The RUBY_VERSIONconstant contains the release version number, but you will need to split the dots to get the MAJOR, MINOR, and TEENY if those values are important to you:
>> major, minor, teeny = RUBY_VERSION.split(".")
=> ["1", "9", "3"]
>> teeny
=> "3"
That said, Ruby version numbers are specifically designed to be ASCII-comparable, so it is common to see code like this for simple version checks:
if RUBY_VERSION >= "1.9.3"
#...
end
Patch level can typically be ignored, because there are no API changes in patch level releases, only bug fixes and security patches. Hope that helps!
Looks like Minor is just reporting on the library minor - ok. So all I am left with is the ruby_version string - better than nothing.
# /usr/bin/ruby -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(LIBRUBY_SO))'
libruby.so.1.9.1
# /usr/bin/ruby -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(ruby_version))'
1.9.3-p286
ruby 1.8 shows this:
$ /usr/bin/ruby -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(LIBRUBY_SO))'
libruby1.8.so.1.8.7
and ruby 1.9.2-p320 this:
$ ruby -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(LIBRUBY_SO))'
libruby.so.1.9.1
So I guess mystery solved.