ruby环境

#ruby环境

##ruby运行文件的选项:

-e script 这个选项运行script中的代码,如果制定的-e选项多于一个,他们关联的脚本会被看作独立的代码行

ruby -e "puts 111" #输出111

-I path 这个选项把path中的目录加到全局$LOAD_PATH数组的起始处,load和require方法会在该数组包含的目录中搜索加载文件

ruby -I "/Users/fangxiang/work" xxx.rb

-r library 这个选项用于在运行程序前加载给定的library,作用就像在程序的首部增加如下代码行:

require 'library'

-d, --debug 这两个选项把全局变量$DEBUG和$VERBOSE设置为true,他们可以被程序或库代码使用,用来打印调试信息或别的操作

##预定义的类和模块

可以通过类似下面的代码在环境中检测预定义的模块、类和异常:

puts Module.constants.sort.select {|x| Object.const_get(x.to_s).instance_of? Module}
	
输出:
Comparable
Config
Enumerable
Errno
Exception2MessageMapper
FileTest
GC
Gem
IRB
Kernel
Marshal
Math
MonitorMixin
ObjectSpace
Process
RbConfig
Readline
RubyToken
Signal

获取类:

Module.constants.sort.select do |x|
  c = eval(x.to_s)
  c.is_a? Class and not c.ancestors.include? Exception
end

返回:

[:Array, :BasicObject, :Bignum, :Binding, :Class, :Complex, :ConditionVariable, :Data, :Date, :Dir, :Encoding, :Enumerator, :FalseClass, :Fiber, :File, :Fixnum, :Float, :Hash, :IO, :Integer, :MatchData, :Method, :Module, :Monitor, :Mutex, :NilClass, :Numeric, :Object, :Proc, :Queue, :Random, :Range, :Rational, :Regexp, :RubyLex, :RubyVM, :SizedQueue, :String, :Struct, :Symbol, :Thread, :ThreadGroup, :Time, :TrueClass, :UnboundMethod]

获取异常:

Module.constants.sort.select do |x|
  c = eval(x.to_s)
  c.is_a? Class and c.ancestors.include? Exception
end

返回:

[:ArgumentError, :EOFError, :EncodingError, :Exception, :FiberError, :FloatDomainError, :IOError, :IndexError, :Interrupt, :KeyError, :LoadError, :LocalJumpError, :NameError, :NoMemoryError, :NoMethodError, :NotImplementedError, :RangeError, :RegexpError, :RuntimeError, :ScriptError, :SecurityError, :SignalException, :StandardError, :StopIteration, :SyntaxError, :SystemCallError, :SystemExit, :SystemStackError, :ThreadError, :TypeError, :ZeroDivisionError] 

##顶级常量

获取环境中的顶级常量:

puts Module.constants.sort.reject{|x| eval(x.to_s).is_a? Module}

输出:

ARGF 一个IO对象,它把ARGV中指定的所有文件虚拟连接起来成为一个文件。如果ARGV为空,那么它表示标准输入。是$<的同义词
ARGV 一个数组,包含所有命令行指定的参数,是$*的同义词
CROSS_COMPILING
ENV 一个对象,其行为像一个哈希对象,可以通过它访问解释器中可用的环境变量
FALSE 
NIL
RUBYGEMS_ACTIVATION_MONITOR
RUBY_COPYRIGHT
RUBY_DESCRIPTION
RUBY_ENGINE
RUBY_PATCHLEVEL 用于指示解释器补丁号的字符串
RUBY_PLATFORM 用于指示ruby解释器运行平台的字符串
RUBY_RELEASE_DATE 用于指示ruby解释器发布日期的字符串
RUBY_REVISION 用于指示解释器支持的ruby语言版本号的字符串
RUBY_VERSION
STDERR 标准错误流,是$stderr变量的默认值
STDIN 标准输入流,是$stdin变量的默认值
STDOUT 标准输出流,是$stdout的默认值
TOPLEVEL_BINDING 一个Binding对象,用于表示顶级范围的绑定
TRUE

##全局变量

获取ruby解释器预定义的全局变量列表:

global_variables.sort

返回:

[:$!, :$", :$$, :$&, :$', :$*, :$+, :$,, :$-0, :$-F, :$-I, :$-K, :$-W, :$-a, :$-d, :$-i, :$-l, :$-p, :$-v, :$-w, :$., :$/, :$0, :$1, :$2, :$3, :$4, :$5, :$6, :$7, :$8, :$9, :$:, :$;, :$<, :$=, :$>, :$?, :$@, :$DEBUG, :$FILENAME, :$KCODE, :$LOADED_FEATURES, :$LOAD_PATH, :$PROGRAM_NAME, :$SAFE, :$VERBOSE, :$\, :$_, :$`, :$binding, :$load_modules, :$stderr, :$stdin, :$stdout, :$~] 

###全局设置全局变量

$* ARGV常量的同义词

$$ 当前ruby进程的进程ID,只读的

$? 最后一个结束程序的退出状态,它是只读且线程局部的

$DEBUG, $-d 如果在命令行中设置了-d或--debug属性,这两个变量值为true

$LOADED_FEATURES, $" 一个字符串数组,表示已加载的文件名,只读的

$LOAD_PATH, $:, $-I 一个包含一组目录名的字符串数组,在使用load和require方法来加载文件时,会在这些目录下进行查找

$PROGRAM, $O 表示当前执行的ruby程序文件名

$SAFE 当前执行程序的安全级别

###异常处理全局变量

$! 最后抛出的异常对象

$@ 最后一个异常对象的调用对战,等价于$!.backtrace

###流和文本处理的全局变量

$_ Kernel模块方法gets和readline所读的最后一个字符串,这个值是线程局部且方法局部的

$< ARGF流的一个只读同义词

$stdin 标准输入流,初始值是常量STDIN,不过很多ruby程序不从它读取信息,而是使用ARGF或$<进行读取

$stdout, $> 标准输出流,是Kernel模块中各种打印方法的目标流:比如puts、print、printf等

$stderr 标准错误,它的初始值是常量STDERR

$FILENAME ARGF当前所读取的文件名,等价于ARGF.filename,只读的

$. 从当前输入文件中最后读取行的行号,等价于ARGF.lineno

$/, $-0 输入记录分隔符(默认是换行符),gets和readline方法默认使用这个值来确定行边界,可以通过解释器选项-0来设定这个值

$\ 输出记录分隔符,默认值是nil,如果设置了非nil值,在每次调用print(不过其他输出方法不会如此,比如puts)后,会打印这个分隔符

$, print方法打印输出各个参数间的分隔符,也是Array.join方法的默认分隔符,默认值是nil

$;, $-F split方法使用的默认字段分隔符,默认值是nil

###模式匹配全局变量

$~ 最后一次模式匹配操作所生成的MatchData对象,它是线程局部且方法局部的。

$& 最近匹配的文本,等价于$~[0],只读的,而且是线程局部、方法局部的,继承自$~

$` 最新匹配的文本之前的字符串,等价于$~.pre_match,只读的,而且是线程局部、方法局部的,继承自$~

$+ 最后一次模式匹配中最后一个成功匹配分组的字符串,只读的,而且是线程局部、方法局部的,继承自$~

##进程和创建子进程

在ruby中另一种实现并发性的方式是使用多个ruby进程,这可以通过fork函数或同义词方法Process.fork来实现:

fork {
	puts "hello from child process: #{$$}"
}
puts "hello from the parent process: #{$$}"

通过这种方式,原始的ruby进程继续执行代码块之后的代码,而新创建的ruby进程则执行代码块中的代码。

如果不使用代码块,fork的行为会有所不同。在父进程中,对fork函数的调用会返回一个整数值,它代表新创建子进程的ID;而在子进程中,同样对fork的调用则返回nil。

pid = fork

if pid
  puts "hello from parent process: #{$$}"
  puts "created child process #{pid}"
else
  puts "hello from child process: #{$$}"
  pid2 = fork
  puts "child fork pid: #{pid2}"
end

输出:

hello from parent process: 2042
created child process 2043
hello from child process: 2043
child fork pid: 2044
child fork pid:

进程和线程的一个十分重要的区别在于进程不共享内存。当调用fork时,新创建的ruby进程会精确复制父进程。但是任何对进程状态的修改都在自身的地址空间中完成,子进程不能修改父进程的数据结构,而父进程也不能修改子进程中的数据结构。

如果想让父进程和子进程进行通信,可以使用open函数,并用“|-”作为它的第一个参数。这个函数为新创建的ruby进程打开一个管道,在父进程和子进程中都会把控制权交给open所关联的代码块。在子进程中,代码块所接收的参数为nil;而在父进程中,代码块接收一个IO对象,对这个IO对象进行读取可以得到子进程所写的数据;而对这个IO对象中写入的数据可以通过子进程的标准输入读出:

open("|-", "r+") do |child|
  if child
    #this is the parent process
    child.puts "hello world" #发送数据到子进程
    response = child.gets #读取子进程输出的数据
    puts "child said: #{response}"
  else
    #this is the child process
    from_parent = gets #从父进程读取数据
    STDERR.puts "parent said: #{from_parent}"
    puts "hi mon!" #发送数据到父进程
  end
end

输出:

parent said: hello world
child said: hi mon!

Kernel.exec函数在与fork或open配合使用时有特别的用途。前面我们看到可以使用`和system向操作系统发送任意的命令,不过这两个方法都是同步方式的,在命令完成前不会返回。如果想在一个单独的进程中执行系统命令,首先要使用fork来创建子进程,然后调用在子进程中的exec来运行命令。对exec的调用永远不会返回,它用新创建的进程替代当前进程。exec的参数与system的相同。如果只有一个参数,该参数被当作外壳命令处理;如果有多个参数,第一个参数被当作可执行命令,剩下的参数成为可执行命令的“ARGV”变量:

open("|-", "r") do |child|
  if child
    #this is the parent process
    files = child.readlines #read the output of our child
    puts "files:", files.inspect
    child.close
  else
    #this is the child process
    exec "ls", "-l" #
  end
end

输出:

files:
["total 152\n", "-rw-r--r--   1 fangxiang  staff  5481  2  9 13:29 acceptance_test.rb\n", "-rw-r--r--   1 fangxiang  staff  1657 12  4 10:16 update_google_hosts.rb\n"]

##捕获信号

绝大多数操作系统支持对当前运行的进程发送异步信号。当用户键入Ctrl+C来中止一个程序时,所发生的事情就是异步信号的一个例子。大多数的外壳程序在接收到Ctrl+C后,将发送一个名为“SIGINT”(用于中断运行)的信号,该信号的默认的处理方式是中止程序,ruby允许程序捕获信号并定义自己的信号处理程序。这是通过Kernel.trap方法(或同义词方法Signal.trap)实现的。

例如,如果不想让用户使用Ctrl+C退出程序,可以这样:

trap "SIGINT" {
	puts "Ignoring SIGINT"
}

除了给trap方法传递一个代码块,也可以给他传递一个等价的Proc对象。如果只是想简单忽略一个信号,可以用字符串“IGNORE”作为第二个参数。如果用“DEFAULT”作为第二个参数,操作系统将恢复该信号的默认处理方式。

##结束程序

一些相关的Kernel方法用于结束程序或相关的动作,exit函数是最直接的,它抛出一个SystemExit异常,如果该异常没有被捕获,则导致程序退出。不过在退出前,END块及任何用Kernel.at_exit注册的处理方法被执行。如果要立刻退出,可以使用exit!方法,该方法不会执行END块等。这两个方法接受一个整数参数,它代表进程退出码,将被提供给操作系统。Process.exit和Process.exit!是这两个Kernel函数的同义词函数。

abort函数向标准输出流打印指定的错误信息,然后调用exit(1)

abort "aaa"

fail是raise的同义词方法,它一般在捕获到须要程序结束的异常时使用。像abort一样,fail在程序退出时显示一个消息,例如:

fail "the end"

warn函数与abort和fail有点关系:它向标准错误流打印一个警告消息(除非通过-WO选项显示禁止警告)。不过这个函数不会抛出异常或退出程序。

warn "aaa"

sleep不会让程序退出,只是让程序(或至少是程序当前运行的线程)暂停指定的秒数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值