Ruby 编程中的预定义元素与实用快捷方式
1. 预定义模块和类
当 Ruby 1.8 解释器启动时,会定义以下模块:
- Comparable
- FileTest
- Marshal
- Precision
- Enumerable
- GC
- Math
- Process
- Errno
- Kernel
- ObjectSpace
- Signal
同时,会定义以下类:
| 类名 | 类名 | 类名 | 类名 |
| — | — | — | — |
| Array | File | Method | String |
| Bignum | Fixnum | Module | Struct |
| Binding | Float | NilClass | Symbol |
| Class | Hash | Numeric | Thread |
| Continuation | IO | Object | ThreadGroup |
| Data | Integer | Proc | Time |
| Dir | MatchData | Range | TrueClass |
| FalseClass | MatchingData | Regexp | UnboundMethod |
还会定义以下异常类:
- ArgumentError
- NameError
- SignalException
- EOFError
- NoMemoryError
- StandardError
- Exception
- NoMethodError
- SyntaxError
- FloatDomainError
- NotImplementedError
- SystemCallError
- IOError
- RangeError
- SystemExit
- IndexError
- RegexpError
- SystemStackError
- Interrupt
- RuntimeError
- ThreadError
- LoadError
- ScriptError
- TypeError
- LocalJumpError
- SecurityError
- ZeroDivisionError
Ruby 1.9 增加了以下模块、类和异常:
- BasicObject
- FiberError
- Mutex
- VM
- Fiber
- KeyError
- StopIteration
你可以使用以下代码检查预定义的模块、类和异常:
# Print all modules (excluding classes)
puts Module.constants.sort.select {|x| eval(x.to_s).instance_of? Module}
# Print all classes (excluding exceptions)
puts Module.constants.sort.select {|x|
c = eval(x.to_s)
c.is_a? Class and not c.ancestors.include? Exception
}
# Print all exceptions
puts Module.constants.sort.select {|x|
c = eval(x.to_s)
c.instance_of? Class and c.ancestors.include? Exception
}
2. 顶级常量
Ruby 解释器启动时,除了前面列出的模块和类,还会定义以下顶级常量。定义了同名常量的模块仍可通过在前面加上
::
来访问这些顶级常量。你可以使用以下命令列出顶级常量:
ruby -e 'puts Module.constants.sort.reject{|x| eval(x.to_s).is_a? Module}'
以下是一些顶级常量的介绍:
| 常量名 | 描述 |
| — | — |
| ARGF | 一个 IO 对象,可访问 ARGV 中指定的文件的虚拟串联,如果 ARGV 为空,则访问标准输入。它是
$<
的同义词。 |
| ARGV | 一个数组,包含命令行中指定的参数。它是
$*
的同义词。 |
| DATA | 如果程序文件中包含单独一行的
__END__
标记,则该常量定义为一个流,可访问
__END__
之后的文件行。如果程序文件中不包含
__END__
,则该常量未定义。 |
| ENV | 一个行为类似于哈希的对象,可访问解释器的环境变量设置。 |
| FALSE |
false
的弃用同义词。 |
| NIL |
nil
的弃用同义词。 |
| RUBY_PATCHLEVEL | 一个字符串,表示解释器的补丁级别。 |
| RUBY_PLATFORM | 一个字符串,表示 Ruby 解释器的平台。 |
| RUBY_RELEASE_DATE | 一个字符串,表示 Ruby 解释器的发布日期。 |
| RUBY_VERSION | 一个字符串,表示解释器支持的 Ruby 语言版本。 |
| STDERR | 标准错误输出流。它是
$stderr
变量的默认值。 |
| STDIN | 标准输入流。它是
$stdin
变量的默认值。 |
| STDOUT | 标准输出流。它是
$stdout
变量的默认值。 |
| TOPLEVEL_BINDING | 一个 Binding 对象,表示顶级作用域中的绑定。 |
| TRUE |
true
的弃用同义词。 |
3. 全局变量
Ruby 解释器预定义了许多全局变量,你可以在程序中使用。这些变量有一些特殊之处,有些名称中使用了标点符号(
English.rb
模块定义了这些标点符号的英文替代名称,如果你想使用这些详细名称,可以在程序中添加
require 'English'
),有些是只读的,有些是线程局部的,还有一些是方法局部的。
你可以使用以下命令获取 Ruby 解释器预定义的全局变量的完整列表:
ruby -e 'puts global_variables.sort'
若要在列表中包含
English
模块的详细名称,可以尝试:
ruby -rEnglish -e 'puts global_variables.sort'
3.1 全局设置
这些全局变量保存配置设置,并指定 Ruby 程序运行环境的信息,如命令行参数:
| 变量名 | 描述 | 英文同义词 |
| — | — | — |
|
$*
|
ARGV
常量的只读同义词。 |
$ARGV
|
|
$$
| 当前 Ruby 进程的进程 ID,只读。 |
$PID
,
$PROCESS_ID
|
|
$?
| 最后终止的进程的退出状态,只读且线程局部。 |
$CHILD_STATUS
|
|
$DEBUG
,
$-d
| 如果命令行中设置了
-d
或
--debug
选项,则设置为
true
。 | |
|
$KCODE
,
$-K
| 在 Ruby 1.8 中,该变量保存一个字符串,表示当前的文本编码,其值为 “NONE”、“UTF8”、“SJIS” 或 “EUC”,可以使用解释器选项
-K
设置该值。在 Ruby 1.9 中,该变量不再起作用,使用它会导致警告。 | |
|
$LOADED_FEATURES
,
$"
| 一个字符串数组,列出已加载的文件,只读。 | |
|
$LOAD_PATH
,
$:
,
$-I
| 一个字符串数组,保存使用
load
和
require
方法加载文件时要搜索的目录。该变量是只读的,但你可以更改它所引用的数组的内容,例如在路径中追加或前置新目录。 | |
|
$PROGRAM_NAME
,
$0
| 包含当前正在执行的 Ruby 程序的文件的名称。如果程序从标准输入读取,则值为 “-”;如果使用
-e
选项指定程序,则值为 “-e”。注意,这与
$FILENAME
不同。 | |
|
$SAFE
| 程序执行的当前安全级别,详细信息请参考相关内容。可以使用
-T
选项从命令行设置该变量的值,该变量的值是线程局部的。 | |
|
$VERBOSE
,
$-v
,
$-w
| 如果指定了
-v
、
-w
或
--verbose
命令行选项,则为
true
;如果指定了
-W0
,则为
nil
;否则为
false
。你可以将该变量设置为
nil
以抑制所有警告。 | |
3.2 异常处理全局变量
以下两个全局变量在捕获异常时的
rescue
子句中很有用:
| 变量名 | 描述 | 英文同义词 |
| — | — | — |
|
$!
| 最后抛出的异常对象。也可以在
rescue
子句的声明中使用
=>
语法访问异常对象,该变量的值是线程局部的。 |
$ERROR_INFO
|
|
$@
| 最后一个异常的堆栈跟踪,相当于
$!.backtrace
,该值是线程局部的。 |
$ERROR_POSITION
|
3.3 流和文本处理全局变量
以下全局变量是 IO 流和影响文本处理
Kernel
方法默认行为的变量:
| 变量名 | 描述 | 英文同义词 |
| — | — | — |
|
$_
|
Kernel
方法
gets
和
readline
最后读取的字符串,该值是线程局部和方法局部的。许多
Kernel
方法隐式地对
$_
进行操作。 |
$LAST_READ_LINE
|
|
$<
|
ARGF
流的只读同义词:一个类似 IO 的对象,可访问命令行中指定的文件的虚拟串联,如果未指定文件,则访问标准输入。
Kernel
读取方法(如
gets
)从该流读取。注意,该流并不总是与
$stdin
相同。 |
$DEFAULT_INPUT
|
|
$stdin
| 标准输入流,该变量的初始值是常量
STDIN
。许多 Ruby 程序从
ARGF
或
$<
读取,而不是
$stdin
。 | |
|
$stdout
,
$>
| 标准输出流,也是
Kernel
打印方法(如
puts
、
print
、
printf
等)的目标。 |
$DEFAULT_OUTPUT
|
|
$stderr
| 标准错误输出流,该变量的初始值是常量
STDERR
。 | |
|
$FILENAME
| 当前从
ARGF
读取的文件的名称,相当于
ARGF.filename
,只读。 | |
|
$.
| 当前输入文件中最后读取的行号,相当于
ARGF.lineno
。 |
$NR
,
$INPUT_LINE_NUMBER
|
|
$/
,
$-0
| 输入记录分隔符(默认为换行符),
gets
和
readline
默认使用该值来确定行边界。你可以使用
-0
解释器选项设置该值。 |
$RS
,
$INPUT_RECORD_SEPARATOR
|
|
$\
| 输出记录分隔符,默认值为
nil
,但在使用
-l
解释器选项时设置为
$/
。如果不为
nil
,则在每次调用
print
(但不是
puts
或其他输出方法)后输出该分隔符。 |
$ORS
,
$OUTPUT_RECORD_SEPARATOR
|
|
$,
|
print
参数之间的输出分隔符,也是
Array.join
的默认分隔符,默认值为
nil
。 |
$OFS
,
$OUTPUT_FIELD_SEPARATOR
|
|
$;
,
$-F
|
split
使用的默认字段分隔符,默认值为
nil
,你可以使用
-F
解释器选项指定一个值。 |
$FS
,
$FIELD_SEPARATOR
|
|
$F
| 如果 Ruby 解释器使用
-a
选项以及
-n
或
-p
选项调用,则定义该变量。它保存当前输入行的字段,由
split
返回。 | |
3.4 模式匹配全局变量
以下全局变量是线程局部和方法局部的,由任何
Regexp
模式匹配操作设置:
| 变量名 | 描述 | 英文同义词 |
| — | — | — |
|
$~
| 最后一次模式匹配操作产生的
MatchData
对象,该值是线程局部和方法局部的。这里描述的其他模式匹配全局变量都由此派生。将该变量设置为新的
MatchData
对象会改变其他变量的值。 |
$MATCH_INFO
|
|
$&
| 最近匹配的文本,相当于
$~[0]
,只读、线程局部、方法局部,由
$~
派生。 |
$MATCH
|
|
$`` | 最后一次模式匹配中匹配之前的字符串,相当于
$~.pre_match
,只读、线程局部、方法局部,由
$~
派生。 |
$PREMATCH
|
|
$’
| 最后一次模式匹配中匹配之后的字符串,相当于
$~.post_match
,只读、线程局部、方法局部,由
$~
派生。 |
$POSTMATCH
|
|
$+
| 最后一次模式匹配中最后一个成功匹配的组对应的字符串,只读、线程局部、方法局部,由
$~
派生。 |
$LAST_PAREN_MATCH` |
3.5 命令行选项全局变量
Ruby 定义了许多与解释器命令行选项的状态或值对应的全局变量:
| 变量名 | 描述 |
| — | — |
|
$-a
| 如果指定了解释器选项
-a
,则为
true
;否则为
false
,只读。 |
|
$-i
| 如果未指定解释器选项
-i
,则为
nil
。否则,该变量设置为
-i
指定的备份文件扩展名。 |
|
$-l
| 如果指定了
-l
选项,则为
true
,只读。 |
|
$-p
| 如果指定了解释器选项
-p
,则为
true
;否则为
false
,只读。 |
|
$-W
| 在 Ruby 1.9 中,该全局变量指定当前的详细级别。如果使用了
-W0
选项,则为 0;如果使用了
-w
、
-v
或
--verbose
选项,则为 2;否则为 1,只读。 |
4. 预定义全局函数
Kernel
模块定义了许多作为全局函数的私有实例方法,这些方法必须以函数方式调用,无需显式的接收者对象,并且可以在任何地方调用。这些函数可以分为以下几类:
4.1 关键字函数
以下
Kernel
函数的行为类似于语言关键字:
-
block_given?
-
iterator?
-
loop
-
require
-
callcc
-
lambda
-
proc
-
throw
-
catch
-
load
-
raise
4.2 文本输入、输出和操作函数
Kernel
定义了以下函数,其中大多数是 IO 方法的全局变体:
-
format
-
print
-
puts
-
sprintf
-
gets
-
printf
-
readline
-
p
-
putc
-
readlines
在 Ruby 1.8(但不是 1.9)中,
Kernel
还定义了以下隐式对
$_
操作的
String
方法的全局变体:
-
chomp
-
chomp!
-
chop
-
chop!
-
gsub
-
gsub!
-
scan
-
split
-
sub
-
sub!
4.3 操作系统方法
以下
Kernel
函数允许 Ruby 程序与操作系统进行交互:
-
`
-
fork
-
select
-
system
-
trap
-
exec
-
open
-
syscall
-
test
4.4 警告、失败和退出
以下
Kernel
函数用于显示警告、抛出异常、使程序退出或注册程序终止时要运行的代码块:
-
abort
-
at_exit
-
exit
-
exit!
-
fail
-
warn
4.5 反射函数
以下
Kernel
函数是 Ruby 反射 API 的一部分:
-
binding
-
set_trace_func
-
caller
-
singleton_method_added
-
eval
-
singleton_method_removed
-
global_variables
-
singleton_method_undefined
-
local_variables
-
trace_var
-
method_missing
-
untrace_var
-
remove_instance_variable
4.6 转换函数
以下
Kernel
函数尝试将其参数转换为新类型:
-
Array
-
Float
-
Integer
-
String
4.7 其他
Kernel
函数
以下其他
Kernel
函数不属于上述类别:
-
autoload
-
rand
-
srand
-
autoload?
-
sleep
5. 用户定义的全局函数
在类或模块声明中使用
def
定义方法且未指定接收者对象时,该方法将作为
self
(即正在定义的类或模块)的公共实例方法创建。而在顶级作用域(即不在任何类或模块中)使用
def
定义方法有两个重要区别:首先,顶级方法是
Object
的实例方法(即使
self
不是
Object
);其次,顶级方法始终是私有的。
5.1 顶级
self
:主对象
顶级方法成为
Object
的实例方法,但
self
是一个特殊的对象,称为 “主” 对象。主对象的类是
Object
,它有一个单例
to_s
方法,返回字符串 “main”。
顶级方法定义在
Object
中意味着它们会被所有对象(包括
Module
和
Class
)继承,并且(如果未被重写)可以在任何类或实例方法定义中使用。由于顶级方法是私有的,因此必须像函数一样调用,无需显式的接收者。通过这种方式,Ruby 在其严格的面向对象框架内模拟了过程式编程范式。
6. 实用提取和报告快捷方式
Ruby 受到脚本语言 Perl 的影响,包含许多全局函数,便于编写从文件中提取信息并生成报告的程序。在面向对象范式中,输入和输出函数是
IO
的方法,字符串操作函数是
String
的方法,但为了实用起见,有一些全局函数可以从预定义的输入和输出流进行读写。此外,许多这些函数隐式地对特殊的方法局部变量
$_
进行操作,该变量保存从输入流读取的最后一行。
6.1 输入函数
全局函数
gets
、
readline
和
readlines
与同名的
IO
方法类似,但它们隐式地对
$<
流(也可作为常量
ARGF
使用)进行操作,并且隐式地设置
$_
。
$<
的行为类似于 IO 对象,但它不是 IO 对象。如果
ARGV
数组为空,则
$<
与
STDIN
相同;如果
ARGV
不为空,
$<
会依次读取
ARGV
中的文件。这意味着你的 Ruby 脚本可以在开始从
$<
读取之前修改
ARGV
,也可以在运行时向
ARGV
中添加其他文件。
6.2 已弃用的提取函数
在 Ruby 1.8 及更早版本中,全局函数
chomp
、
chomp!
、
chop
、
chop!
、
gsub
、
gsub!
、
scan
、
split
、
sub
和
sub!
的行为与同名的
String
方法类似,但隐式地对
$_
进行操作。这些全局函数在 Ruby 1.9 中已被移除,因此不应在新代码中使用。
6.3 报告函数
Kernel
定义了许多将输出发送到
$stdout
的全局函数:
-
puts
、
print
、
printf
和
putc
等同于
STDOUT
的同名方法。
puts
会在输出末尾追加换行符,而
print
不会自动追加换行符,但会在设置了
$\
时追加输出记录分隔符。
- 全局函数
p
用于调试,它调用每个参数的
inspect
方法并将结果字符串传递给
puts
。如果需要 “漂亮打印” 调试输出,可以使用
pp
函数。
-
printf
方法期望第一个参数是格式字符串,并将其余参数的值替换到该字符串中,然后输出结果。你也可以使用全局函数
sprintf
或其同义词
format
将结果格式化为字符串,而不将其发送到
$stdout
。
综上所述,Ruby 提供了丰富的预定义元素和实用快捷方式,这些功能在编写脚本和程序时非常有用,但在大型程序中应谨慎使用全局变量和函数,以避免代码的复杂性和不可维护性。通过合理运用这些特性,开发者可以更高效地完成各种任务。
7. 输入函数流程分析
下面我们通过 mermaid 格式的流程图来展示输入函数
gets
、
readline
和
readlines
对
$<
流操作的流程:
graph TD;
A[开始] --> B{ARGV 数组是否为空};
B -- 是 --> C[$< 等同于 STDIN];
B -- 否 --> D[使用 ARGV.shift 获取第一个文件名];
D --> E[打开并读取该文件];
E --> F{是否到达文件末尾};
F -- 否 --> G[继续读取文件内容并设置 $_];
G --> F;
F -- 是 --> H{ARGV 中是否还有文件名};
H -- 是 --> D;
H -- 否 --> I[结束读取];
C --> J[从 STDIN 读取内容并设置 $_];
J --> K[结束读取];
这个流程图清晰地展示了
$<
流在不同情况下的读取逻辑。当
ARGV
为空时,直接从标准输入读取;当
ARGV
不为空时,依次读取
ARGV
中的文件,直到所有文件读取完毕。
8. 报告函数使用示例
以下是一些报告函数的使用示例,帮助你更好地理解它们的功能:
# 使用 puts 输出
puts "Hello, World!"
# 使用 print 输出
print "This is a test. "
print "Another line. ", "\n"
# 使用 printf 格式化输出
name = "John"
age = 30
printf "Name: %s, Age: %d\n", name, age
# 使用 p 进行调试输出
arr = [1, 2, 3]
p arr
# 使用 sprintf 格式化字符串
formatted_str = sprintf "The value is %.2f", 3.14159
puts formatted_str
在这个示例中,我们展示了
puts
、
print
、
printf
、
p
和
sprintf
函数的使用。
puts
会自动添加换行符,
print
可以根据需要控制换行,
printf
用于格式化输出,
p
方便调试,
sprintf
则用于格式化字符串而不直接输出。
9. 全局变量和函数的使用建议
虽然 Ruby 提供了丰富的全局变量和函数,但在使用时需要注意以下几点:
-
避免滥用
:在大型项目中,过多使用全局变量和函数会增加代码的耦合度,降低代码的可维护性。尽量将功能封装在类和模块中,遵循面向对象的设计原则。
-
注意线程安全
:部分全局变量是线程局部的,但仍需注意在多线程环境下的使用,避免出现数据竞争和不一致的问题。
-
兼容性问题
:一些全局变量和函数在不同版本的 Ruby 中可能存在差异,如 Ruby 1.8 和 1.9 中关于
chomp
等函数的变化。在编写代码时,要确保代码的兼容性。
10. 总结
本文详细介绍了 Ruby 编程中的预定义模块、类、顶级常量、全局变量和全局函数,以及实用的提取和报告快捷方式。通过合理运用这些元素,开发者可以更高效地编写 Ruby 脚本和程序。
10.1 主要内容回顾
- 预定义元素 :包括模块、类、异常类、顶级常量等,这些元素在 Ruby 解释器启动时自动定义,为开发提供了基础支持。
- 全局变量 :分为全局设置、异常处理、流和文本处理、模式匹配、命令行选项等几类,各有不同的用途和特点。
- 全局函数 :涵盖关键字函数、文本输入输出和操作函数、操作系统方法、警告失败和退出函数、反射函数、转换函数和其他函数等类别,方便进行各种操作。
-
快捷方式
:受 Perl 影响,提供了一些全局函数和对
$_的隐式操作,便于编写提取信息和生成报告的程序。
10.2 未来展望
随着 Ruby 语言的不断发展,可能会有更多的预定义元素和快捷方式被添加或改进。开发者可以持续关注 Ruby 的官方文档和社区动态,及时掌握新特性,提升开发效率和代码质量。
通过对这些知识的深入理解和合理运用,你可以更好地发挥 Ruby 的优势,编写出高质量、高效率的代码。希望本文能对你的 Ruby 编程学习和实践有所帮助。
超级会员免费看
14

被折叠的 条评论
为什么被折叠?



