想开发一个命令行工具
在使用 Ruby 的过程中我们发现很多实用的命令行工具,比如 rails new abc 会新建一个 rails 项目;gem install mina 会按照名为 mina 的 gem;mina deploy 会自动部署 rails 项目。
我想开发一个命令行工具,比如 max file.txt 可以获得 file.txt 文件中的最大的数字。
OK,下面是我的几个问题:
其实我的问题很简单,就是一个编写命令行工具的一个接口如何实现呢?
#!/usr/bin/env ruby
# max.rb 文件内容
fn=ARGV[0]
puts "file: #{fn} "
n=open(ARGV[0]).read.scan(/[\.\d]+/im).map{|x| x.to_f}.sort[-1]
puts "max val is: #{n} "
编辑 max.rb,把 max.rb 复制到操作系统的 PATH 目录,文件名改为 max, 后缀去掉,就可以用命令行执行 max . 其实 gem 也是一个 ruby 脚本:
▶ type gem
gem 已被录入哈希表 (/usr/bin/gem)
kkar4 -bash kk /tmp/RDP 15:51:05
▶ file /usr/bin/gem
/usr/bin/gem: Ruby script, ASCII text executable
kkar4 -bash kk /tmp/RDP 15:51:09
▶ head /usr/bin/gem
#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
require 'rubygems'
require 'rubygems/gem_runner'
require 'rubygems/exceptions'
▶ chmod +x max.rb
kkar4 -bash kk /tmp/RDP 15:59:31
▶ cp max.rb max
kkar4 -bash kk /tmp/RDP 15:59:34
▶ PATH=$PATH:`pwd`
kkar4 -bash kk /tmp/RDP 15:59:59
▶ max file.txt
file: file.txt
max val is: 9999999999999999
但你举得例子,rails, mina, rake 这都是 gem。在 gem 里,配置 executables 就可以命令行执行了。 https://guides.rubygems.org/specification-reference/#executables
默认可能会生成像这样 spec.executables = spec.files.grep(%r{^bin/*}) { |f| File.basename(f) } ,也就是说,你写到 bin 目录下的文件就可以执行了
“魔法”只有两点:
#!/usr/bin/env ruby
然后把你的文件路径加入终端的 PATH 中,或者复制到可执行的路径下面,如~/.bin
或者/usr/local/bin
DONE
任何语言都可以用来写命令行工具;Ruby 当然也可以;编译型语言的命令行一般是可执行的二进制文件;Shell、Perl、Python、Ruby 等语言基本就是可执行的脚本文件了。
Rails 的命令多是使用 Thor 这个 gem 实现的:https://github.com/erikhuda/thor。具体可以看它的 wiki。
至于手动写一个带有可执行命令的 gem,可以见 https://guides.rubygems.org/make-your-own-gem/#adding-an-executable。可以参考的例子非常多,比如这个:https://github.com/beijingrb/mdopen 。
如果只是运行一个脚本,不管什么系统,关键是把脚本路径加到 PATH 环境里。对于 Windows 应该要让执行程序和脚本扩展名做好关联,否则就得用 ruby + 脚本名称 的方式来运行。
C:\Users\Administrator>where gem
e:\Ruby23\bin\gem.cmd
e:\Ruby23\bin\gem
e:\Ruby23\bin\gem.bat
C:\Users\Administrator>head e:\Ruby23\bin\gem.bat
@ECHO OFF
IF NOT "%~f0" == "~f0" GOTO :WinNT
@"ruby.exe" "e:/Ruby23/bin/gem" %1 %2 %3 %4 %5 %6 %7 %8 %9
GOTO :EOF
:WinNT
@"ruby.exe" "%~dpn0" %*
C:\Users\Administrator>head e:\Ruby23\bin\pry.bat
@ECHO OFF
IF NOT "%~f0" == "~f0" GOTO :WinNT
@"e:\Ruby23\bin\ruby.exe" "e:/Ruby23/bin/pry" %1 %2 %3 %4 %5 %6 %7 %8 %9
GOTO :EOF
:WinNT
@"e:\Ruby23\bin\ruby.exe" "%~dpn0" %*
这 2 个 bat 文件内容差不多