不久前我写了一个很好的小Ruby脚本,我很喜欢它.我想通过判断适当数量的参数来提高它的健壮性:

if ARGV.length != 2 then
  puts "Usage: <command> arg1 arg2"
end

那当然是伪代码.无论如何,在C或C++中,我可以用argv[0]来获取用户用来获取命令的名称,他们是否称之为./myScript.rbmyScript.rb/usr/local/bin/myScript.rb.在Ruby中,我知道ARGV[0]是第一个真参数,ARGV不包含命令名.有没有办法让我拿到这个?

推荐答案

Ruby有三种方法为我们提供被调用脚本的名称:

#!/usr/bin/env ruby

puts "$0            : #{$0}"
puts "__FILE__      : #{__FILE__}"
puts "$PROGRAM_NAME : #{$PROGRAM_NAME}"

将该代码保存为"test.rb"并以多种方式调用,表明脚本在操作系统传递给它时收到了名称.脚本只知道操作系统告诉它什么:

$ ./test.rb 
$0            : ./test.rb
__FILE__      : ./test.rb
$PROGRAM_NAME : ./test.rb

$ ~/Desktop/test.rb 
$0            : /Users/ttm/Desktop/test.rb
__FILE__      : /Users/ttm/Desktop/test.rb
$PROGRAM_NAME : /Users/ttm/Desktop/test.rb

$ /Users/ttm/Desktop/test.rb 
$0            : /Users/ttm/Desktop/test.rb
__FILE__      : /Users/ttm/Desktop/test.rb
$PROGRAM_NAME : /Users/ttm/Desktop/test.rb

在第二个示例中,使用$HOME的~快捷方式调用它,显示操作系统将其替换为扩展路径,与第三个示例中的匹配.在所有情况下,这都是操作系统传递的信息.

使用硬链接和软链接链接到文件显示了一致的行为.我为test1创建了一个硬链接.rb和test2的软链接.rb:

$ ./test1.rb 
$0            : ./test1.rb
__FILE__      : ./test1.rb
$PROGRAM_NAME : ./test1.rb

$ ./test2.rb 
$0            : ./test2.rb
__FILE__      : ./test2.rb
$PROGRAM_NAME : ./test2.rb

在脚本名上使用任何变体启动ruby test.rb都会返回一致的结果.

如果您只想要被调用的文件名,那么可以将File的basename方法与其中一个变量一起使用,或者在分隔符上拆分并获取最后一个元素.

$0__FILE__有一些细微的区别,但对于单个脚本,它们是等效的.

puts File.basename($0)

使用File.basenameFile.extnameFile.dirname方法套件有一些好处.basename接受一个可选参数,即strip的扩展名,因此如果只需要basename而不需要扩展名

File.basename($0, File.extname($0)) 

在不重新设计车轮、不必处理可变长度或缺失延伸件或不正确截断延伸链".rb.txt"的可能性的情况下进行操作,例如:

ruby-1.9.2-p136 :004 > filename = '/path/to/file/name.ext'
 => "/path/to/file/name.ext" 
ruby-1.9.2-p136 :005 > File.basename(filename, File.extname(filename))
 => "name" 
ruby-1.9.2-p136 :006 > filename = '/path/to/file/name.ext' << '.txt'
 => "/path/to/file/name.ext.txt" 
ruby-1.9.2-p136 :007 > File.basename(filename, File.extname(filename))
 => "name.ext" 

Ruby相关问答推荐

Ruby 中无法解释的撬动行为

回声ABC | ruby -p -e "sub('a','A').sub('b', 'B')": 为什么不是 "ABc"?

如何在 ruby​​ 中列出当前范围内的当前可用对象?

Ruby 中有类似 Python 生成器的东西吗?

为什么 Matz Select 在 Ruby 中默认使字符串可变?

CSV.read 第 x 行的非法引用

从Electron邮件中删除签名和回复

如何在 ruby​​ 中针对正则表达式测试整个字符串?

警告! PATH 设置不正确,通常这是由 shell 初始化文件引起的

Ruby 中的文件打开模式

Ruby,生成随机十六进制 colored颜色

rbenv、rvm 和 chruby 有什么区别?

Ruby全局匹配正则表达式?

Ruby Koans 的 test_sharing_hashes 中的附加问题的答案是什么?

如何在 Ruby 中做标准差?

`File` 对象访问模式的区别(即 w+, r+)

如何在没有警告的情况下重新定义 Ruby 常量?

Ruby - Array#<< 和 Array#push 之间的区别

为什么这个 Ruby 对象同时具有 to_s 和 inspect 似乎做同样事情的方法?

查找与给定条件匹配的元素的索引