-

Ruby - 概述

Ruby是一种纯粹的面向对象编程语言。日本的松本由纪子创立于1993年。

您可以在www.ruby-lang.org上的Ruby邮件列表中找到松本松子的名字松下在Ruby社区也被称为Matz。

Ruby是“程序员最好的朋友”。

Ruby具有与Smalltalk,Perl和Python类似的功能。Perl,Python和Smalltalk都是脚本语言。Smalltalk是一种真正的面向对象语言。Ruby,像Smalltalk,是一种完美的面向对象语言。使用Ruby语法比使用Smalltalk语法容易得多。

Ruby的特点

你需要的工具

对于执行本教程中探讨的示例,您将需要最新的计算机,如Intel Core i3或i5,至少需要2GB的RAM(推荐4GB的RAM)。您还需要以下软件 -

本教程将提供使用Ruby创建GUI,网络和Web应用程序的必要技能。还将探讨扩展和嵌入Ruby应用程序。

下一步是什么?

下一章将指导您了解可以获取Ruby及其文档的位置。最后,它指示您如何安装Ruby并准备开发Ruby应用程序的环境。

Ruby - 环境设置

在线运行

我们已经在线设置了Ruby Programming环境,因此可以在线编译和执行所有可用的示例。你可以学习的同时,在线验证程序。随意修改任何示例并在线执行。

使用我们的在线编译器可在尝试下面的例子CodingGround

#!/usr/bin/ruby -w

puts "Hello, Ruby!";

对于本教程中给出的大多数示例,您将在右上角的网站代码部分找到一个Try it选项,该部分将带您进入在线编译器。所以只是利用它,享受你的学习。

本地环境设置

如果您仍然愿意为Ruby编程语言设置环境,那么我们继续。本教程将向您介绍与环境设置相关的所有重要主题。我们建议您先浏览以下主题,然后继续进行 -

热门Ruby编辑器

要编写你的Ruby程序,你需要一个编辑器 -

交互式Ruby(IRb)

交互式Ruby(IRb)提供了一个用于实验的shell。在IRb shell中,您可以立即逐个查看表达式结果。

这个工具与Ruby安装一起,所以你没有什么可以额外的使IRb工作。

只需在命令提示符下键入irb,交互式Ruby会话即可开始如下:

$irb
irb 0.6.1(99/09/16)
irb(main):001:0> def hello
irb(main):002:1> out = "Hello World"
irb(main):003:1> puts out
irb(main):004:1> end
nil
irb(main):005:0> hello
Hello World
nil
irb(main):006:0>

不要担心我们在这里做了什么。您将在以后的章节中了解所有这些步骤。

下一步是什么?

我们假设现在你有一个工作的Ruby环境,你准备好编写第一个Ruby程序。下一章将教你如何编写Ruby程序。

Ruby - 语法

让我们用ruby写一个简单的程序。所有ruby文件将扩展名为.rb所以,将以下源代码放在test.rb文件中。

#!/usr/bin/ruby -w

puts "Hello, Ruby!";

在这里,我们假设你的Ruby解释器在/ usr / bin目录下可用。现在,尝试运行这个程序如下 -

$ ruby test.rb

输出结果如下 -

Hello, Ruby!

您已经看到一个简单的Ruby程序,现在让我们看看一些与Ruby语法相关的基本概念。

Ruby程序中的空白

Ruby代码中通常忽略诸如空格和制表符之类的空格字符,除非它们以字符string形式出现。然而有时候,它们被用来解释不明确的语句。当启用-w选项时,这种解释会产生警告。

a + b is interpreted as a+b ( Here a is a local variable)
a  +b is interpreted as a(+b) ( Here a is a method call)

Ruby程序中的行结束

Ruby将分号和换行符解释为语句的结尾。但是,如果Ruby遇到运算符,例如行尾的+, - 或反斜杠,则表示语句的继续。

Ruby标识符

标识符是变量,常量和方法的名称。Ruby标识符区分大小写。这意味着Ram和RAM是Ruby中两个不同的标识符。

Ruby标识符名称可能包含字母数字字符和下划线字符(_)。

保留字

以下列表显示了Ruby中的保留字。这些保留字不能用作常量或变量名。但是,它们可以用作方法名称。

开始 do 下一个 然后
结束 other 真正
别名 埃尔斯夫 undef
&& 结束 || 除非
开始 确保 重做 直到
break false 拯救 什么时候
案件 对于 重试
class 如果 return
def __文件__
定义? 模块 __线__

Ruby中的文档

“这里的文档”是指从多行创建字符string。遵循<<您可以指定一个字符string或标识符来终止字符string文字,并且当前行之后的所有行都是字符string的值。

如果引用了终止符,则引号类型决定了面向行的字符string文字的类型。注意<<和终止符之间不能有空格。

这里有不同的例子 -

#!/usr/bin/ruby -w

print <<EOF
    This is the first way of creating
    here document ie. multiple line string.
EOF

print <<"EOF";                # same as above
    This is the second way of creating
    here document ie. multiple line string.
EOF

print <<`EOC`                 # execute commands
	echo hi there
	echo lo there
EOC

print <<"foo", <<"bar"  # you can stack them
	I said foo.
foo
	I said bar.
bar

输出结果如下 -

    This is the first way of creating
    her document ie. multiple line string.
    This is the second way of creating
    her document ie. multiple line string.
hi there
lo there
        I said foo.
        I said bar.

Ruby BEGIN声明

用法

BEGIN {
   code
}

声明在程序运行之前要调用的代码

#!/usr/bin/ruby

puts "This is main Ruby Program"

BEGIN {
   puts "Initializing Ruby Program"
}

输出结果如下 -

Initializing Ruby Program
This is main Ruby Program

Ruby END语句

用法

END {
   code
}

声明在程序结束时调用的代码

#!/usr/bin/ruby

puts "This is main Ruby Program"

END {
   puts "Terminating Ruby Program"
}
BEGIN {
   puts "Initializing Ruby Program"
}

输出结果如下 -

Initializing Ruby Program
This is main Ruby Program
Terminating Ruby Program

Ruby注释

一个注释隐藏了一行,一行的一部分,或者是Ruby解释器的几行。您可以使用行的开头的哈希字符(#)

# I am a comment. Just ignore me.

或者,在声明或表达之后,注释可能在同一行上 -

name = "Madisetti" # This is again comment

您可以如下注释多行:

# This is a comment.
# This is a comment, too.
# This is a comment, too.
# I said that already.

这是另一种形式。这个块注释从解释器中隐藏了几行,其中= begin / = end -

= begin
This is a comment.
This is a comment, too.
This is a comment, too.
I said that already.
= end

Ruby - 类和对象

Ruby是一个完美的面向对象编程语言。面向对象编程语言的特点包括 -

这些特性已经在面向对象Ruby的一章中探讨过了

面向对象的程序涉及类和对象。类是创建单个对象的蓝图。在面向对象的术语中,我们说你的自行车被称为自行车的物体的一个实例

以任何车辆为例。它包括轮子,马力,燃料或燃气罐容量。这些特征形成了车辆类的数据成员。借助这些特点,您可以区分一辆车与另一辆。

车辆还可以具有某些功能,例如停止,驾驶和加速。即使这些功能也构成了Vehicle类的数据成员。因此,您可以将类定义为特征和功能的组合。

一类车可以定义为 -

Class Vehicle {

   Number no_of_wheels
   Number horsepower
   Characters type_of_tank
   Number Capacity
   Function speeding {
	
   }
   Function driving {
	
   }
   Function halting {
	
   }
}

通过为这些数据成员分配不同的值,您可以形成类Vehicle的几个实例。例如,一架飞机有三个轮子,马力为1,000,燃料为坦克类型,容量为100升。同样的方式,一辆汽车有四个轮子,二十马力,燃气作为坦克的类型,容量为25升。

定义Ruby中的类

要通过使用Ruby实现面向对象的编程,您需要首先学习如何在Ruby中创建对象和类。

Ruby中的类始终以关键字类和类的名称开头。这个名字应该始终是在首都的首都。课程客户可以显示为 -

class Customer
end

您可以使用关键字结束终止类中的所有数据成员都在类定义和结束关键字之间。

Ruby类中的变量

Ruby提供了四种类型的变量 -

使用类变量@@ no_of_customers,可以确定正在创建的对象数。这样可以获得客户数量。

class Customer
   @@no_of_customers = 0
end

使用新方法在Ruby中创建对象

对象是类的实例。现在您将学习如何在Ruby中创建类的对象。您可以通过使用的类的方法在Ruby中创建对象

方法new是一种独特的方法,它是在Ruby库中预定义的。新方法属于方法。

以下是创建Customer类的两个对象cust1和cust2的示例:

cust1 = Customer. new
cust2 = Customer. new

在这里,cust1和cust2是两个对象的名称。您写的对象名称后跟等号(=),之后类名将跟随。然后,点运算符和关键字new将跟随。

自定义方法来创建Ruby对象

您可以将参数传递给方法new,这些参数可用于初始化类变量。

当您计划使用参数声明方法时,需要在创建类时声明方法initialize

初始化方法是一种特殊类型的方法中,当将要执行的新的类的方法被调用的参数。

以下是创建initialize方法的示例 -

class Customer
   @@no_of_customers = 0
   def initialize(id, name, addr)
      @cust_id = id
      @cust_name = name
      @cust_addr = addr
   end
end

在这个例子中,你使用id,nameaddr声明initialize方法作为局部变量。这里,defend用于定义Ruby方法初始化您将在后续章节中更多地了解方法。

初始化方法中,将这些局部变量的值传递给实例变量@cust_id,@cust_name和@cust_addr。这里局部变量包含与新方法一起传递的值。

现在,您可以创建如下对象 -

cust1 = Customer.new("1", "John", "Wisdom Apartments, Ludhiya")
cust2 = Customer.new("2", "Poul", "New Empire road, Khandala")

Ruby类中的成员函数

在Ruby中,函数称为方法。中的每个方法都以关键字def开头,后跟方法名称。

方法名称始终以小写字母表示您可以使用关键字end在Ruby中结束一个方法

以下是定义Ruby方法的示例 -

class Sample
   def function
      statement 1
      statement 2
   end
end

这里,语句1语句2类Sample内部方法函数的一部分这些数据可以是任何有效的Ruby语句。例如,我们可以把方法放在打印你好红宝石如下-

class Sample
   def hello
      puts "Hello Ruby!"
   end
end

现在在下面的例子中,创建一个Sample类的对象并调用hello方法并查看结果 -

#!/usr/bin/ruby

class Sample
   def hello
      puts "Hello Ruby!"
   end
end

# Now using above class to create objects
object = Sample. new
object.hello

输出结果如下 -

Hello Ruby!

简单案例研究

这是一个案例研究,如果你想做更多的练习与类和对象。

Ruby类案例研究

Ruby - 变量,常量和文字

变量是存储器位置,它保存任何程序要使用的数据。

Ruby支持的变体有五种类型。您也已经在上一章中简要介绍了这些变量。本章介绍了这五种类型的变量。

Ruby全局变量

全局变量以$开头。未初始化的全局变量的值为nil,并使用-w选项生成警告。

赋予全局变量改变全局状态。不建议使用全局变量。他们使程序隐藏。

下面是一个示例,显示全局变量的用法。

#!/usr/bin/ruby

$global_variable = 10
class Class1
   def print_global
      puts "Global variable in Class1 is #$global_variable"
   end
end
class Class2
   def print_global
      puts "Global variable in Class2 is #$global_variable"
   end
end

class1obj = Class1.new
class1obj.print_global
class2obj = Class2.new
class2obj.print_global

这里$ global_variable是一个全局变量。输出结果如下 -

注意 - 在Ruby中,您可以通过在该变量或常量之前放置一个哈希(#)字符来访问任何变量或常量的值。

Global variable in Class1 is 10
Global variable in Class2 is 10

Ruby实例变量

实例变量以@开头。未初始化的实例变量的值为nil,并使用-w选项生成警告。

下面是一个示例,显示实例变量的用法。

#!/usr/bin/ruby

class Customer
   def initialize(id, name, addr)
      @cust_id = id
      @cust_name = name
      @cust_addr = addr
   end
   def display_details()
      puts "Customer id #@cust_id"
      puts "Customer name #@cust_name"
      puts "Customer address #@cust_addr"
   end
end

# Create Objects
cust1 = Customer.new("1", "John", "Wisdom Apartments, Ludhiya")
cust2 = Customer.new("2", "Poul", "New Empire road, Khandala")

# Call Methods
cust1.display_details()
cust2.display_details()

这里,@cust_id,@cust_name和@cust_addr是实例变量。输出结果如下 -

Customer id 1
Customer name John
Customer address Wisdom Apartments, Ludhiya
Customer id 2
Customer name Poul
Customer address New Empire road, Khandala

Ruby类变量

类变量以@@开始,并且必须先进行初始化,然后才能在方法定义中使用。

引用未初始化的类变量会产生错误。类变量在定义类变量的类或模块的后代中共享。

覆盖类变量使用-w选项生成警告。

下面是一个示例,显示了类变量的用法 -

#!/usr/bin/ruby

class Customer
   @@no_of_customers = 0
   def initialize(id, name, addr)
      @cust_id = id
      @cust_name = name
      @cust_addr = addr
   end
   def display_details()
      puts "Customer id #@cust_id"
      puts "Customer name #@cust_name"
      puts "Customer address #@cust_addr"
   end
   def total_no_of_customers()
      @@no_of_customers += 1
      puts "Total number of customers: #@@no_of_customers"
   end
end

# Create Objects
cust1 = Customer.new("1", "John", "Wisdom Apartments, Ludhiya")
cust2 = Customer.new("2", "Poul", "New Empire road, Khandala")

# Call Methods
cust1.total_no_of_customers()
cust2.total_no_of_customers()

这里@@ no_of_customers是一个类变量。输出结果如下 -

Total number of customers: 1
Total number of customers: 2

Ruby本地变量

局部变量以小写字母或_开头。局部变量的范围从class,module,def或do到相应的end或从块的开放大括号到其关闭大括号{}。

当引用未初始化的局部变量时,它被解释为对没有参数的方法的调用。

对未初始化的局部变量的分配也用作变量声明。变量开始存在,直到达到当前作用域的结尾。当Ruby解析程序时,确定局部变量的生命周期。

在上面的例子中,局部变量是id,name和addr。

Ruby常数

常数以大写字母开头。在类或模块中定义的常量可以从该类或模块中访问,并且可以全局访问在类或模块外部定义的常量。

方法中可能不会定义常量。引用未初始化的常量会产生错误。对已经初始化的常量进行分配会产生警告。

#!/usr/bin/ruby

class Example
   VAR1 = 100
   VAR2 = 200
   def show
      puts "Value of first Constant is #{VAR1}"
      puts "Value of second Constant is #{VAR2}"
   end
end

# Create Objects
object = Example.new()
object.show

这里VAR1和VAR2是常数。输出结果如下 -

Value of first Constant is 100
Value of second Constant is 200

Ruby伪虚拟变量

它们是具有局部变量的外观的特殊变量,但是它的行为就像常量。您不能为这些变量分配任何值。

Ruby基本文字

Ruby用于文字的规则是简单直观的。本节将介绍所有基本的Ruby Literals。

Integers

Ruby支持整数。的整数的范围可以从-2 30到2 30-1或-2 62到2 62-1在此范围内的整数是Fixnum类的对象,并且此范围之外的整数存储在Bignum类的对象中

您可以使用可选的前导符号,可选的基本指示符(0表示八进制,0x表示十六进制,或0b代表二进制)写入整数,后跟相应基数字符string。下划线字符在数字字符string中被忽略。

您还可以获取与ASCII字符相对应的整数值,或者通过使用问号来排除序列。

123                  # Fixnum decimal
1_234                # Fixnum decimal with underline
-500                 # Negative Fixnum
0377                 # octal
0xff                 # hexadecimal
0b1011               # binary
?a                   # character code for "a"
?
                  # code for a newline (0x0a)
12345678901234567890 # Bignum

- 类和对象在本教程的另一章中进行了说明。

float数字

Ruby支持整数。他们也是数字,但是小数位。浮点数是Float类的对象,可以是以下任何一个 -

123.4                # floating point value
1.0e6                # scientific notation
4E20                 # dot not required
4e+20                # sign before exponential

字符string文字

Ruby字符string是8位字节的简单序列,它们是String类的对象。双引号字符string允许替换和反斜杠符号,但单引号字符string不允许替换,并允许仅对和"进行反斜杠符号

#!/usr/bin/ruby -w

puts "escape using """;
puts "That"s right";

输出结果如下 -

escape using ""
That"s right

您可以使用序列#{expr}将任何Ruby表达式的值替换为字符string在这里,expr可以是任何ruby表达式。

#!/usr/bin/ruby -w

puts "Multiplication Value : #{24*60*60}";

输出结果如下 -

Multiplication Value : 86400

反斜杠符号

以下是Ruby支持的反斜杠符号列表 -

符号 字符代表
n 换行(0x0a)
r 回车(0x0d)
F Formfeed(0x0c)
b 退格(0x08)
一个 贝尔(0x07)
e 逃脱(0x1b)
s 空格(0x20)
nnn 八进制符号(n为0-7)
xnn 十六进制符号(n为0-9,af或AF)
cx, Cx Control-x
Mx Meta-x(c | 0x80)
M- Cx 元控制x
X 字符x

有关Ruby字符string的更多详细信息,请访问Ruby字符string

Ruby数组

Ruby Array的文字通过在方括号之间放置逗号分隔的一系列对象引用来创建。后面的逗号被忽略。

#!/usr/bin/ruby

ary = [  "fred", 10, 3.14, "This is a string", "last element", ]
ary.each do |i|
   puts i
end

输出结果如下 -

fred
10
3.14
This is a string
last element

有关Ruby数组的更多详细信息,请访问Ruby数组

红宝石哈希

一个文字的Ruby哈希是通过在一个大括号之间放置一个键/值对的列表来创建的,逗号或键和值之间的序列=>。后面的逗号被忽略。

#!/usr/bin/ruby

hsh = colors = { "red" => 0xf00, "green" => 0x0f0, "blue" => 0x00f }
hsh.each do |key, value|
   print key, " is ", value, "
"
end

输出结果如下 -

red is 3840
green is 240
blue is 15

有关Ruby Hash的更多细节,请浏览Ruby Hash

红宝石山脉

一个范围代表一个间隔。一组开始和结束的值。可以使用s..e和s ... e文字或Range.new创建范围。

使用..从开始到结束运行的范围包括。使用...创建的排除结束值。当用作迭代器时,范围返回序列中的每个值。

范围(1..5)表示包括1,2,3,4,5值,范围(1 ... 5)表示包括1,2,3,4值。

#!/usr/bin/ruby

(10..15).each do |n| 
   print n, " " 
end

输出结果如下 -

10 11 12 13 14 15

有关Ruby Ranges的更多详细信息,请访问Ruby Ranges

Ruby - 运算符

Ruby支持一组丰富的运算符,就像您所期望的一种现代语言一样。大多数运算符实际上是方法调用。例如,a + b被解释为一个+(b),其中变量a引用的对象中的+方法b为参数来调用。

对于每个运算符(+ - * /%**&| ^ << >> && ||),有一个相应的缩写赋值运算符(+ = - =等)。

Ruby算术运算符

假设变量a保持10,变量b保持20,则 -

没有 操作符和说明
1 +

加法 - 在运算符的两边添加值。

a + b将给予30
2 -

减法 - 从左手操作数减去右手操作数。

a - b会给-10
3 *

乘法 - 在运算符的两边乘以值。

a * b会给予200
4 /

部门 - 用右手操纵数除数左手操作数。

b / a将给予2
5

模数 - 用右手操作数除左手操作数并返回余数。

b%a会给0
6 **

指数 - 对运算符执行指数(幂)计算。

a ** b将给予权力20

Ruby比较运算符

假设变量a保持10,变量b保持20,则 -

没有 操作符和说明
1 ==

检查两个操作数的值是否相等,如果是,则条件成立。

(a == b)不正确。
2 !=

检查两个操作数的值是否相等,如果值不等于条件成立。

(a!= b)是真的。
3 >

检查左操作数的值是否大于右操作数的值,如果是,则条件成为真。

(a> b)不正确。
4 <

检查左操作数的值是否小于右操作数的值,如果是,则条件成为真。

(a <b)是真的。
5 > =

检查左操作数的值是否大于或等于右操作数的值,如果是,则条件成为真。

(a> = b)不是真的。
6 <=

检查左操作数的值是否小于或等于右操作数的值,如果是,则条件成为真。

(a <= b)是真的。
7 <=>

组合比较运算符。如果第一个操作数等于秒,则返回0,如果第一个操作数大于第二个,则返回1,如果第一个操作数小于第二个则返回-1。

(a <=> b)返回-1。
8 ===

用于测试case语句的when子句中的相等性。

(1 ... 10)=== 5返回true。
9 .eql?

如果接收者和参数具有相同的类型和相等的值,则为真。

1 == 1.0返回true,但是1.eql?(1.0)是false。
10 等于?

如果接收方和参数具有相同的对象标识,则为真。

如果aObj与bObj重复,那么aObj == bObj为true,则a.equal?bObj为false,但a.equal?aObj为true。

Ruby分配运算符

假设变量a保持10,变量b保持20,则 -

没有 操作符和说明
1 =

简单赋值运算符,将右侧操作数的值分配给左侧操作数。

c = a + b将a + b的值分配给c
2 + =

添加AND赋值运算符,将右操作数添加到左操作数,并将结果分配给左操作数。

c + = a等价于c = c + a
3 - =

减去AND赋值运算符,从左操作数中减去右操作数,并将结果分配给左操作数。

c * - = a等价于c = c - a
4 * =

乘以AND赋值运算符,将右操作数与左操作数相乘,并将结果分配给左操作数。

c * = a等价于c = c * a
5 / =

除以AND赋值运算符,将左操作数与右操作数分开,并将结果分配给左操作数。

c / = a等价于c = c / a
6 %=

模数AND分配运算符,使用两个操作数来计算模数,并将结果分配给左操作数。

c%= a等价于c = c%a
7 ** =

指数AND赋值运算符对运算符进行指数(幂)运算,并将值分配给左操作数。

c ** = a等价于c = c ** a

Ruby并行作业

Ruby还支持并行分配变量。这样可以使用一行Ruby代码初始化多个变量。例如 -

a = 10
b = 20
c = 30

这可能会使用并行分配更快地声明 -

a, b, c = 10, 20, 30

并行分配对于交换保存在两个变量中的值也是有用的 -

a, b = b, c

Ruby Bitwise运算符

按位运算符对位执行,并进行逐位运算。

假设a = 60; 和b = 13; 现在以二进制格式,他们将如下 -

 a    =  0011 1100
 b    =  0000 1101
 ------------------
 a&b  =  0000 1100
 a|b  =  0011 1101
 a^b  =  0011 0001
 ~a   =  1100 0011

Ruby语言支持以下Bitwise运算符。

没有 操作符和说明
1

如果二进制AND运算符存在于两个操作数中,则二进制AND运算符将对结果复制一位。

(a&b)将给予12,即0000 1100
2 |

二进制OR运算符如果存在于任一操作数中,则复制一位。

(a | b)将给出61,即0011 1101
3 ^

二进制XOR操作符复制该位,如果它设置在一个操作数中,而不是两者。

(a ^ b)将给出49,即0011 0001
4

二进制补码运算符是一元的,具有“翻转”位的作用。

(a)将给出-61,由于符号二进制数,其为2的补码形式为1100 0011。
5 <<

二进制左移操作符。左操作数值左移由右操作数指定的位数。

一个<< 2将给予240,即1111 0000
6 >>

二进制右移操作符。左操作数值被右操作数指定的位移动。

a >> 2将给出15,这是0000 1111

Ruby逻辑运算符

Ruby语言支持以下逻辑运算符

假设变量a保持10,变量b保持20,则 -

没有 操作符和说明
1

称为逻辑AND运算符。如果两个操作数都为真,则条件成立。

(a和b)是真的。
2

称为逻辑或运算符。如果两个操作数中的任何一个为非零,则条件成立。

(a或b)是真的。
3 &&

称为逻辑AND运算符。如果两个操作数都不为零,则条件成立。

(a && b)是真的。
4 ||

称为逻辑或运算符。如果两个操作数中的任何一个为非零,则条件成立。

(a || b)为真。
5

称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑NOT运算符将为false。

!(a && b)是假的。
6

称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑NOT运算符将为false。

不(a && b)是假的。

Ruby三元运算符

还有一个叫三元运算符的运算符。它首先计算一个表达式的true或false值,然后根据评估结果执行两个给定语句之一。条件运算符具有这种语法 -

没有 操作符和说明
1

条件表达式

如果条件是真的?那么值X:否则值Y

红宝石范围运算符

Ruby中的序列范围用于创建一系列连续的值 - 由起始值,结束值和值之间的范围组成。

在Ruby中,这些序列使用“..”和“...”范围运算符创建。双点格式创建一个包含范围,而三点形式创建一个排除指定高值的范围。

没有 操作符和说明
1 .. ..

创建从起点到终点的范围。

1..10创建范围从1到10(含)。
2 ...

创建从起始点到终点独占的范围。

1 ... 10创建范围从1到9。

Ruby定义?经营者

定义?是一个特殊的操作符,采用方法调用的形式来确定传递的表达式是否被定义。它返回表达式的描述字符string,如果表达式未定义,则返回nil

有各种用法定义?操作符

用法1

defined? variable # True if variable is initialized

例如

foo = 42
defined? foo    # => "local-variable"
defined? $_     # => "global-variable"
defined? bar    # => nil (undefined)

用法2

defined? method_call # True if a method is defined

例如

defined? puts        # => "method"
defined? puts(bar)   # => nil (bar is not defined here)
defined? unpack      # => nil (not defined here)

用法3

# True if a method exists that can be called with super user
defined? super

例如

defined? super     # => "super" (if it can be called)
defined? super     # => nil (if it cannot be)

用法4

defined? yield   # True if a code block has been passed

例如

defined? yield    # => "yield" (if there is a block passed)
defined? yield    # => nil (if there is no block)

红宝石点“。” 和双冒号“::”操作符

您可以通过使用模块名称和句点名称来调用模块方法,并使用模块名称和两个冒号引用常量。

::是一元运算符,其允许:一个类或模块中定义的常量,实例方法和类方法中,待从类或模块以外的任何地方访问。

记住在Ruby中,类和方法也可以被认为是常量。

您需要在:: Const_name前面加上一个返回相应类或模块对象的表达式。

如果不使用前缀表达式,则默认使用主Object类。

这里有两个例子 -

MR_COUNT = 0         # constant defined on main Object class
module Foo
   MR_COUNT = 0
   ::MR_COUNT = 1    # set global count to 1
   MR_COUNT = 2      # set local count to 2
end
puts MR_COUNT        # this is the global constant
puts Foo::MR_COUNT   # this is the local "Foo" constant

第二个例子

CONST = " out there"
class Inside_one
   CONST = proc {" in there"}
   def where_is_my_CONST
      ::CONST + " inside one"
   end
end
class Inside_two
   CONST = " inside two"
   def where_is_my_CONST
      CONST
   end
end
puts Inside_one.new.where_is_my_CONST
puts Inside_two.new.where_is_my_CONST
puts Object::CONST + Inside_two::CONST
puts Inside_two::CONST + CONST
puts Inside_one::CONST
puts Inside_one::CONST.call + Inside_two::CONST

Ruby运算符优先级

下表列出了从最高优先级到最低优先级的所有运算符。

方法 操作符 描述
:: 恒定分辨率算子
[] [] = 元素参考,元素集
** 指数(提高权力)
+ - 不,补,一元加减(最后两个的方法名称是+ @和 - @)
* /% 乘,除和模
+ - 加减
>> << 左右向右移位
按位“AND”
^ | 按位异或“OR”和常规的“OR”
<= <>> = 比较运算符
<=> == ===!= =! 平等和模式匹配运算符(!=和!可能不被定义为方法)
  && 逻辑"AND"
  || 逻辑"OR"
  .. ... 范围(包括和排他性)
  三元如果 - 否则
  =%= {/ = - = + = | =&= >> = << = * = && = || = ** = 分配
  定义? 检查指定的符号是否定义
  逻辑否定
  或者 逻辑构成

- 方法列中“是 ”的运算符实际上是方法,因此可能会被覆盖。

Ruby - 注释

注释是Ruby代码中的注释行,在运行时被忽略。单行注释以#个字符开头,它们从#延伸到行尾,如下所示:

#!/usr/bin/ruby -w

# This is a single line comment.

puts "Hello, Ruby!"

执行时,上述程序产生以下结果 -

Hello, Ruby!

Ruby Multiline注释

您可以使用= begin= end语法来注释多行,如下所示:

#!/usr/bin/ruby -w

puts "Hello, Ruby!"

=begin
This is a multiline comment and con spwan as many lines as you
like. But =begin and =end should come in the first line only. 
=end

执行时,上述程序产生以下结果 -

Hello, Ruby!

确保尾随注释远离代码,并且易于区分。如果块中存在多个尾随注释,请对齐它们。例如 -

@counter      # keeps track times page has been hit
@siteCounter  # keeps track of times all pages have been hit

Ruby - 如果... else,case,除非

Ruby提供了现代语言很常见的条件结构。在这里,我们将解释Ruby中可用的所有条件语句和修饰符。

Ruby if ... else语句

用法

if conditional [then]
   code...
[elsif conditional [then]
   code...]...
[else
   code...]
end

如果表达式用于条件执行。falsenil是false,其他的都是true。注意Ruby使用elsif,而不是if elifif。

如果条件为真,执行代码如果条件不为真,则执行else子句中指定的代码

如果一个表达式的条件从由代码保留字分离然后,换行,或分号。

#!/usr/bin/ruby

x = 1
if x > 2
   puts "x is greater than 2"
elsif x <= 2 and x!=0
   puts "x is 1"
else
   puts "I can"t guess the number"
end
x is 1

Ruby如果修饰符

用法

code if condition

如果条件为真,执行代码

#!/usr/bin/ruby

$debug = 1
print "debug
" if $debug

输出结果如下 -

debug

Ruby除非声明

用法

unless conditional [then]
   code
[else
   code ]
end

如果条件为false,则执行代码如果条件为true,则执行else子句中指定的代码。

#!/usr/bin/ruby

x = 1 
unless x>2
   puts "x is less than 2"
 else
   puts "x is greater than 2"
end

输出结果如下 -

x is less than 2

除非修饰符

用法

code unless conditional

如果条件为false,则执行代码

#!/usr/bin/ruby

$var =  1
print "1 -- Value is set
" if $var
print "2 -- Value is set
" unless $var

$var = false
print "3 -- Value is set
" unless $var

输出结果如下 -

1 -- Value is set
3 -- Value is set

Ruby案例声明

用法

case expression
[when expression [, expression ...] [then]
   code ]...
[else
   code ]
end

比较由case指定的表达式和使用===运算符时指定的表达式,并执行与之匹配的when子句代码

表达由当子句指定被评价为左操作数。如果no子句匹配,则case会执行else子句的代码

语句的表达是从代码由保留字然后,换行,或分号隔开。因此 -

case expr0
when expr1, expr2
   stmt1
when expr3, expr4
   stmt2
else
   stmt3
end

基本上类似于以下 -

_tmp = expr0
if expr1 === _tmp || expr2 === _tmp
   stmt1
elsif expr3 === _tmp || expr4 === _tmp
   stmt2
else
   stmt3
end

#!/usr/bin/ruby

$age =  5
case $age
when 0 .. 2
   puts "baby"
when 3 .. 6
   puts "little child"
when 7 .. 12
   puts "child"
when 13 .. 18
   puts "youth"
else
   puts "adult"
end

输出结果如下 -

little child

红宝石 - 循环

Ruby中的循环用于执行相同的代码块指定次数。本章详细介绍了Ruby支持的所有循环语句。

Ruby while语句

用法

while conditional [do]
   code
end

执行代码,而条件是真实的。循环的条件是从分离代码由保留字做,换行,反斜线或分号。

#!/usr/bin/ruby

$i = 0
$num = 5

while $i < $num  do
   puts("Inside the loop i = #$i" )
   $i +=1
end

输出结果如下 -

Inside the loop i = 0
Inside the loop i = 1
Inside the loop i = 2
Inside the loop i = 3
Inside the loop i = 4

Ruby而修饰符

用法

code while condition

OR

begin 
  code 
end while conditional

执行代码,而条件是真实的。

如果while修饰符遵循没有拯救或确认子句begin语句,则在对条件进行求值之前执行代码

#!/usr/bin/ruby

$i = 0
$num = 5
begin
   puts("Inside the loop i = #$i" )
   $i +=1
end while $i < $num

输出结果如下 -

Inside the loop i = 0
Inside the loop i = 1
Inside the loop i = 2
Inside the loop i = 3
Inside the loop i = 4

Ruby直到声明

until conditional [do]
   code
end

执行代码,而条件是假的。语句的条件是分开的代码被保留字,换行或分号。

#!/usr/bin/ruby

$i = 0
$num = 5

until $i > $num  do
   puts("Inside the loop i = #$i" )
   $i +=1;
end

输出结果如下 -

Inside the loop i = 0
Inside the loop i = 1
Inside the loop i = 2
Inside the loop i = 3
Inside the loop i = 4
Inside the loop i = 5

红宝石直到修饰符

用法

code until conditional

OR

begin
   code
end until conditional

执行代码,而条件是假的。

如果直到修饰符遵循没有拯救或确认子句begin语句,则在评估条件之前执行代码一次

#!/usr/bin/ruby

$i = 0
$num = 5
begin
   puts("Inside the loop i = #$i" )
   $i +=1;
end until $i > $num

输出结果如下 -

Inside the loop i = 0
Inside the loop i = 1
Inside the loop i = 2
Inside the loop i = 3
Inside the loop i = 4
Inside the loop i = 5

Ruby for Statement

用法

for variable [, variable ...] in expression [do]
   code
end

表达式中的每个元素执行一次代码

#!/usr/bin/ruby

for i in 0..5
   puts "Value of local variable is #{i}"
end

在这里,我们定义了范围0..5。0..5中的声明将允许从0到5(包括5)范围内的值。输出结果如下 -

Value of local variable is 0
Value of local variable is 1
Value of local variable is 2
Value of local variable is 3
Value of local variable is 4
Value of local variable is 5

A for ... in循环几乎完全相当于以下 -

(expression).each do |variable[, variable...]| code end

除了for循环不会为局部变量创建新的范围。用于循环的表达从分离代码由保留字做,一个新行,或分号。

#!/usr/bin/ruby

(0..5).each do |i|
   puts "Value of local variable is #{i}"
end

输出结果如下 -

Value of local variable is 0
Value of local variable is 1
Value of local variable is 2
Value of local variable is 3
Value of local variable is 4
Value of local variable is 5

Ruby break声明

用法

break

终止最内部的循环。如果在块内调用(终止方法返回nil),则终止具有关联块的方法。

#!/usr/bin/ruby

for i in 0..5
   if i > 2 then
      break
   end
   puts "Value of local variable is #{i}"
end

输出结果如下 -

Value of local variable is 0
Value of local variable is 1
Value of local variable is 2

Ruby下一个声明

用法

next

跳转到最内部循环的下一个迭代。如果在块内调用(终止收益或调用返回零),则终止块的执行。

#!/usr/bin/ruby

for i in 0..5
   if i < 2 then
      next
   end
   puts "Value of local variable is #{i}"
end

输出结果如下 -

Value of local variable is 2
Value of local variable is 3
Value of local variable is 4
Value of local variable is 5

Ruby重做声明

用法

redo

重新启动最内部循环的此迭代,而不检查循环条件。如果在块内调用重新启动产量调用

#!/usr/bin/ruby

for i in 0..5
   if i < 2 then
      puts "Value of local variable is #{i}"
      redo
   end
end

输出结果如下,并将进入无限循环 -

Value of local variable is 0
Value of local variable is 0
............................

Ruby重试声明

用法

retry

如果retry出现在begin表达式的rescue子句中,请从begin body的开头重新启动。

begin
   do_something # exception raised
rescue
   # handles error
   retry  # restart from beginning
end

如果重试出现在迭代器中,块或for表达式的正文将重新启动迭代器调用。迭代器的参数被重新评估。

for i in 1..5
   retry if some_condition # restart from i == 1
end

#!/usr/bin/ruby

   for i in 0..5
      if i > 2
puts "Value of local variable is #{i}"
end

输出结果如下,并将进入无限循环 -

Value of local variable is 1
Value of local variable is 2
Value of local variable is 1
Value of local variable is 2
Value of local variable is 1
Value of local variable is 2
............................

Ruby - 方法

Ruby方法与任何其他编程语言中的函数非常相似。Ruby方法用于将一个或多个可重复语句捆绑到一个单元中。

方法名称应以小写字母开头。如果您开始使用大写字母的方法名称,Ruby可能会认为它是一个常量,因此可能会错误地解析该调用。

在调用它们之前应该定义方法,否则Ruby会为未定义的方法调用引发异常。

用法

def method_name [( [arg [= default]]...[, * arg [, &expr ]])]
   expr..
end

所以,你可以定义一个简单的方法如下 -

def method_name 
   expr..
end

你可以表示一个接受这样的参数的方法 -

def method_name (var1, var2)
   expr..
end

您可以为参数设置默认值,如果调用方法而不传递必需的参数,则将使用该值。

def method_name (var1 = value1, var2 = value2)
   expr..
end

每当调用简单的方法时,只写下方法名称,如下所示:

method_name

但是,当您使用参数调用方法时,可以将方法名称与参数一起编写,例如 -

method_name 25, 30

使用参数的方法最重要的缺点是每当您调用这些方法时,都需要记住参数的数量。例如,如果一个方法接受三个参数,只传递两个参数,那么Ruby会显示错误。

#!/usr/bin/ruby

def test(a1 = "Ruby", a2 = "Perl")
   puts "The programming language is #{a1}"
   puts "The programming language is #{a2}"
end
test "C", "C++"
test

输出结果如下 -

The programming language is C
The programming language is C++
The programming language is Ruby
The programming language is Perl

从方法返回值

默认情况下,Ruby中的每个方法都返回一个值。这个返回的值将是最后一个语句的值。例如 -

def test
   i = 100
   j = 10
   k = 0
end

该方法在被调用时将返回最后声明的变量k

Ruby返回语句

ruby中return语句用于从Ruby方法返回一个或多个值。

用法

return [expr[`," expr...]]

如果给出两个以上的表达式,则包含这些值的数组将是返回值。如果没有给出表达式,nil将返回值。

return

OR

return 12

OR

return 1,2,3

看看这个例子 -

#!/usr/bin/ruby

def test
   i = 100
   j = 200
   k = 300
return i, j, k
end
var = test
puts var

输出结果如下 -

100
200
300

可变参数数

假设你声明一个方法需要两个参数,每当你调用这个方法时,你需要传递两个参数。

但是,Ruby允许您声明使用可变数量参数的方法。让我们来看一下这个样本 -

#!/usr/bin/ruby

def sample (*test)
   puts "The number of parameters is #{test.length}"
   for i in 0...test.length
      puts "The parameters are #{test[i]}"
   end
end
sample "Zara", "6", "F"
sample "Mac", "36", "M", "MCA"

在这段代码中,您已经声明了一个接受一个参数测试的方法示例。但是,该参数是一个可变参数。这意味着该参数可以占用任意数量的变量。所以,上面的代码将产生以下结果 -

The number of parameters is 3
The parameters are Zara
The parameters are 6
The parameters are F
The number of parameters is 4
The parameters are Mac
The parameters are 36
The parameters are M
The parameters are MCA

类方法

当方法在类定义之外定义时,默认情况下该方法被标记为private另一方面,默认情况下,类定义中定义的方法被标记为public。模块的默认可见性和私有标记可以通过模块公开私有更改

每当你想访问一个类的方法,你首先需要实例化类。然后,使用该对象,您可以访问该类的任何成员。

Ruby给你一种方法来访问一个方法而不实例化一个类。让我们看看如何声明和访问类方法 -

class Accounts
   def reading_charge
   end
   def Accounts.return_date
   end
end

查看方法return_date如何声明。它以类名声明,后跟一个句点,后跟方法的名称。您可以直接访问此类方法,如下所示:

Accounts.return_date

要访问此方法,您不需要创建类帐户的对象。

Ruby别名声明

这给了方法或全局变量的别名。别名不能在方法体内定义。该方法的别名保持当前方法的定义,即使方法被覆盖。

为编号的全局变量($ 1,$ 2,...)创建别名是禁止的。覆盖内置的全局变量可能会导致严重的问题。

用法

alias method-name method-name
alias global-variable-name global-variable-name

alias foo bar
alias $MATCH $&

这里我们为bar定义了foo别名,$ MATCH是$&

Ruby undef语句

这取消了方法定义。一个民主基金不能出现在方法体中。

通过使用undef别名,类的接口可以独立于超类进行修改,但注意可能会通过内部方法调用self来破坏程序。

用法

undef method-name

要定义一个名为bar的方法,请执行以下操作:

undef bar

Ruby - 块

您已经看到Ruby如何定义方法,您可以在其中放置数量的语句,然后调用该方法。类似地,Ruby有一个Block的概念。

用法

block_name{
   statement1
   statement2
   ..........
}

在这里,您将学习通过使用简单的yield语句来调用块您还将学习使用带有参数的yield语句来调用块。您将使用两种类型的yield语句来检查示例代码

收益表

我们来看看yield语句的一个例子 -

#!/usr/bin/ruby

def test
   puts "You are in the method"
   yield
   puts "You are again back to the method"
   yield
end
test {puts "You are in the block"}

输出结果如下 -

You are in the method
You are in the block
You are again back to the method
You are in the block

您还可以使用yield语句传递参数。这是一个例子 -

#!/usr/bin/ruby

def test
   yield 5
   puts "You are in the method test"
   yield 100
end
test {|i| puts "You are in the block #{i}"}

输出结果如下 -

You are in the block 5
You are in the method test
You are in the block 100

这里,yield语句被写入后跟参数。甚至可以传递多个参数。在块中,您可以在两条垂直线(||)之间放置一个变量来接受参数。因此,在上述代码中,yield 5语句将值5作为参数传递给测试块。

现在,看下面的语句 -

test {|i| puts "You are in the block #{i}"}

这里,在变量i中接收值5 现在,请遵守以下声明-

puts "You are in the block #{i}"

这个put语句的输出是 -

You are in the block 5

如果要传递多个参数,则yield语句将变为 -

yield a, b

和块是 -

test {|a, b| statement}

参数将以逗号分隔。

块和方法

您已经看到块和方法可以如何相互关联。通常使用来自与块相同名称的方法的yield语句来调用块。所以你写 -

#!/usr/bin/ruby

def test
  yield
end
test{ puts "Hello world"}

此示例是实现块的最简单方法。您可以使用yield语句调用测试块

但是如果方法的最后一个参数前面加上&,那么可以将块传递给此方法,并将该块分配给最后一个参数。如果*和&都存在于参数列表中,则应该稍后再来。

#!/usr/bin/ruby

def test(&block)
   block.call
end
test { puts "Hello World!"}

输出结果如下 -

Hello World!

BEGIN和END块

每个Ruby源文件都可以在文件加载(BEGIN块)和程序完成执行(END块)后声明要运行的代码块。

#!/usr/bin/ruby

BEGIN { 
   # BEGIN block code 
   puts "BEGIN code block"
} 

END { 
   # END block code 
   puts "END code block"
}
   # MAIN block code 
puts "MAIN code block"

程序可以包括多个BEGIN和END块。BEGIN块按照遇到的顺序执行。END块以相反的顺序执行。执行时,上述程序产生以下结果 -

BEGIN code block
MAIN code block
END code block

Ruby - 模块和混合

模块是一种将方法,类和常量分组在一起的方法。模块给您两大优势。

模块定义一个命名空间,一个沙盒,您的方法和常量可以在其中播放,而无需担心被其他方法和常量所阻碍。

用法

module Identifier
   statement1
   statement2
   ...........
end

模块常量就像类常量一样被命名,带有一个初始的大写字母。方法定义也类似:模块方法就像类方法一样定义。

与类方法一样,您可以使用模块名称和句点名称来调用模块方法,并使用模块名称和两个冒号引用常量。

#!/usr/bin/ruby

# Module defined in trig.rb file

module Trig
   PI = 3.141592654
   def Trig.sin(x)
   # ..
   end
   def Trig.cos(x)
   # ..
   end
end

我们可以定义一个具有相同功能名称但功能不同的模块 -

#!/usr/bin/ruby

# Module defined in moral.rb file

module Moral
   VERY_BAD = 0
   BAD = 1
   def Moral.sin(badness)
   # ...
   end
end

像类方法一样,只要在模块中定义方法,就可以指定模块名称后跟一个点,然后指定方法名称。

Ruby需要声明

require语句类似于C和C ++的include语句以及Java的import语句。如果第三个程序想要使用任何定义的模块,它可以使用Ruby require语句简单地加载模块文件-

用法

require filename

在这里,不需要给出.rb扩展名和文件名。

$LOAD_PATH << "."

require "trig.rb"
require "moral"

y = Trig.sin(Trig::PI/4)
wrongdoing = Moral.sin(Moral::VERY_BAD)

这里我们使用$ LOAD_PATH <<"。使Ruby意识到必须在当前目录中搜索包含的文件。如果不想使用$ LOAD_PATH,那么可以使用require_relative来包含相对目录中的文件。

重要 - 这里,这两个文件包含相同的函数名称。因此,这将导致代码模糊,同时包括在调用程序中,但模块避免了这种代码模糊,我们可以使用模块名称调用适当的函数。

Ruby包括Statement

你可以在一个类中嵌入一个模块。要在一个类中嵌入一个模块,你可以在类中使用include语句 -

用法

include modulename

如果在单独的文件中定义了一个模块,则需要在将模块嵌入到类中之前使用require语句包含该文件

考虑在support.rb文件中编写的以下模块

module Week
   FIRST_DAY = "Sunday"
   def Week.weeks_in_month
      puts "You have four weeks in a month"
   end
   def Week.weeks_in_year
      puts "You have 52 weeks in a year"
   end
end

现在,您可以将此模块包含在一个类中,如下所示:

#!/usr/bin/ruby
$LOAD_PATH << "."
require "support"

class Decade
include Week
   no_of_yrs = 10
   def no_of_months
      puts Week::FIRST_DAY
      number = 10*12
      puts number
   end
end
d1 = Decade.new
puts Week::FIRST_DAY
Week.weeks_in_month
Week.weeks_in_year
d1.no_of_months

输出结果如下 -

Sunday
You have four weeks in a month
You have 52 weeks in a year
Sunday
120

Ruby中的mixins

在介绍本节之前,我们假设您具有面向对象概念的知识。

当一个类可以继承多个父类的特性时,该类应该显示多个继承。

Ruby不直接支持多重继承,但是Ruby模块有另外一个很好的用途。中间,他们几乎消除了对多重继承的需要,提供了一个名为mixin的工具

Mixins为您提供了一种奇妙的控制方式,可以向类添加功能。然而,当mixin中的代码开始与使用它的类中的代码进行交互时,它们的真实Grav就出现了。

我们来看看下面的示例代码以了解mixin -

module A
   def a1
   end
   def a2
   end
end
module B
   def b1
   end
   def b2
   end
end

class Sample
include A
include B
   def s1
   end
end

samp = Sample.new
samp.a1
samp.a2
samp.b1
samp.b2
samp.s1

模块A由方法a1和a2组成。模块B由方法b1和b2组成。类Sample包含模块A和B。类Sample可以访问所有四种方法,即a1,a2,b1和b2。因此,您可以看到类Sample继承自两个模块。因此,您可以说类Sample显示多个继承或混合

红宝石 - 字符string

Ruby中的String对象持有并操纵一个或多个字节的任意序列,通常表示代表人类语言的字符。

最简单的字符string文字用单引号括起来(撇号字符)。引号内的文字是字符string的值 -

"This is a simple Ruby string literal"

如果您需要在单引号字符string中放置一个撇号,请在其前面加上反斜杠,以便Ruby解释器不认为它会终止字符string -

"Won"t you read O"Reilly"s book?"

反斜杠也可以转义另一个反斜杠,这样第二个反斜杠本身并不被解释为转义字符。

以下是Ruby的字符string相关功能。

表达式替代

表达式替换是使用#{和} - 将任何Ruby表达式的值嵌入到字符string中的一种手段 -

#!/usr/bin/ruby

x, y, z = 12, 36, 72
puts "The value of x is #{ x }."
puts "The sum of x and y is #{ x + y }."
puts "The average was #{ (x + y + z)/3 }."

输出结果如下 -

The value of x is 12.
The sum of x and y is 48.
The average was 40.

一般定界字符string

使用一般分隔的字符string,您可以在一对匹配的任意分隔符字符中创建字符string,例如!,(,{,{等等,前面带有百分比字符(%)Q,q和x具有特殊含义一般分隔的字符string可以是 -

%{Ruby is fun.}  equivalent to "Ruby is fun."
%Q{ Ruby is fun. } equivalent to " Ruby is fun. "
%q[Ruby is fun.]  equivalent to a single-quoted string
%x!ls! equivalent to back tick command output `ls`

逃脱字符

字符编码

Ruby的默认字符集是ASCII,其字符可以由单个字节表示。如果您使用UTF-8或其他现代字符集,则字符可能以一到四个字节表示。

您可以在程序开始时使用$ KCODE更改您的角色集,如下所示:

$KCODE = "u"

字符string内置方法

我们需要一个String对象的实例来调用String方法。以下是创建String对象实例的方法 -

new [String.new(str = "")]

这将返回一个包含str副本的新的字符string对象现在,使用str对象,我们都可以使用任何可用的实例方法。例如 -

#!/usr/bin/ruby

myStr = String.new("THIS IS TEST")
foo = myStr.downcase

puts "#{foo}"

输出结果如下 -

this is test

字符string解包指令

尝试以下示例来解压各种数据。

"abc abc ".unpack("A6Z6")   #=> ["abc", "abc "]
"abc ".unpack("a3a3")           #=> ["abc", " 0000"]
"abc abc ".unpack("Z*Z*")       #=> ["abc ", "abc "]
"aa".unpack("b8B8")                 #=> ["10000110", "01100001"]
"aaa".unpack("h2H2c")               #=> ["16", "61", 97]
"xfexffxfexff".unpack("sS")     #=> [-2, 65534]
"now = 20is".unpack("M*")           #=> ["now is"]
"whole".unpack("xax2aX2aX1aX2a")    #=> ["h", "e", "l", "l", "o"]

Ruby - 数组

Ruby数组是任何对象的有序整数索引集合。数组中的每个元素与索引相关联并由其引用。

数组索引从0开始,如C或Java。假定相对于数组的结尾为负的索引 - 也就是说,-1的索引表示数组的最后一个元素,-2是数组中最后一个元素的下一个,依此类推。

Ruby数组可以容纳诸如String,Integer,Fixnum,Hash,Symbol,甚至其他Array对象的对象。Ruby数组不像其他语言中的数组那么刚性。Ruby数组自动增加,同时向它们添加元素。

创建数组

有许多方法可以创建或初始化数组。一种方法是使用新的类方法 -

names = Array.new

您可以在创建数组时设置数组的大小 -

names = Array.new(20)

数组名称现在具有20个元素的大小或长度。您可以使用size或length方法返回数组的大小 -

#!/ usr / bin / ruby

names = Array 20 
放名size   #返回20个
put名称长度#这也返回20 

输出结果如下 -

20
20

您可以按如下方式为数组中的每个元素分配一个值 -

#!/usr/bin/ruby

names = Array.new(4, "mac")

puts "#{names}"

输出结果如下 -

["mac", "mac", "mac", "mac"]

您还可以使用一个新的块,填充每个元素与块评估的 -

#!/usr/bin/ruby

nums = Array.new(10) { |e| e = e * 2 }

puts "#{nums}"

输出结果如下 -

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

还有另一种方法是Array,[]。它像这样工作 -

nums = Array.[](1, 2, 3, 4,5)

数组创建的另一种形式如下:

nums = Array[1, 2, 3, 4,5]

内核在核心红宝石可用模块有一个数组的方法,其中仅接受一个参数。在这里,该方法将一个范围作为参数来创建一个数组数组 -

#!/usr/bin/ruby

digits = Array(0..9)

puts "#{digits}"

输出结果如下 -

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

数组内置方法

我们需要一个Array对象的实例来调用Array方法。我们已经看到,以下是创建Array对象实例的方法 -

Array.[](...) [or] Array[...] [or] [...]

这将返回一个填充有给定对象的新数组。现在,使用创建的对象,我们可以调用任何可用的实例方法。例如 -

#!/usr/bin/ruby

digits = Array(0..9)

num = digits.at(6)

puts "#{num}"

输出结果如下 -

6

数组指令

尝试以下示例来打包各种数据。

a = [ "a", "b", "c" ]
n = [ 65, 66, 67 ]
puts a.pack("A3A3A3")   #=> "a  b  c  "
puts a.pack("a3a3a3")   #=> "a0000b0000c0000"
puts n.pack("ccc")      #=> "ABC"

输出结果如下 -

a  b  c
abc
ABC

红宝石 - 哈希

哈希是这样的键值对的集合:“employee”=>“salary”。它类似于Array,除了通过任何对象类型的任意键完成索引,而不是整数索引。

通过键或值遍历哈希的顺序可能看起来是任意的,通常不会在插入顺序中。如果您尝试使用不存在的密钥访问哈希,该方法将返回nil

创建哈希

与数组一样,有多种方法可以创建散列。您可以使用新的类方法创建一个空的散列-

months = Hash.new

您也可以使用new来创建具有默认值的哈希值,否则为零

months = Hash.new( "month" )

or

months = Hash.new "month"

当您访问具有默认值的哈希中的任何密钥时,如果该键或值不存在,则访问该哈希将返回默认值 -

#!/usr/bin/ruby

months = Hash.new( "month" )

puts "#{months[0]}"
puts "#{months[72]}"

输出结果如下 -

month
month
#!/usr/bin/ruby

H = Hash["a" => 100, "b" => 200]

puts "#{H["a"]}"
puts "#{H["b"]}"

输出结果如下 -

100
200

您可以使用任何Ruby对象作为键或值,即使是数组,因此以下示例是有效的一个 -

[1,"jan"] => "January"

哈希内置方法

我们需要一个Hash对象的实例来调用Hash方法。正如我们所看到的,以下是创建Hash对象实例的方法 -

Hash[[key =>|, value]* ] or

Hash.new [or] Hash.new(obj) [or]

Hash.new { |hash, key| block }

这将返回一个填充有给定对象的新哈希值。现在使用创建的对象,我们可以调用任何可用的实例方法。例如 -

#!/usr/bin/ruby

$, = ", "
months = Hash.new( "month" )

months = {"1" => "January", "2" => "February"}

keys = months.keys

puts "#{keys}"

输出结果如下 -

["1", "2"]

以下是公共散列方法(假设hash是数组对象)

没有 方法与说明
1 哈希== other_hash

基于它们是否具有相同数量的键值对,以及键值对是否匹配每个散列中的对应对,来测试两个散列是否相等。

2 散列键]

使用键引用哈希值。如果没有找到该键,则返回默认值。

3 hash。[key] = value

将由值给出的与由键给出的键相关联

4 hash.clear

从哈希中删除所有键值对。

5 hash.default(key = nil)

返回hash的默认值,如果未设置,则返回nil =。(如果密钥在哈希中不存在,则返回默认值。)

6 hash.default = obj

设置hash的默认值

7 hash.default_proc

如果哈希是由块创建的,则返回一个块。

8

hash.delete(key)[或]

array.delete(key){| key | 块}

通过哈希中删除键值对如果使用块,则如果未找到对,则返回块的结果。比较delete_if

9 hash.delete_if {| key,value | 块}

哈希中删除键值对,每个块的值计算结果为true

10 hash.each {| key,value | 块}

迭代哈希,为每个键调用一次块,将键值传递为双元素数组。

11 hash.each_key {| key | 块}

迭代哈希,为每个键调用一次块,将密钥作为参数传递。

12 hash.each_key {| key_value_array | 块}

迭代哈希,为每个调用一次块,将作为参数传递。

13 hash.each_key {| value | 块}

迭代哈希,为每个调用一次块,将作为参数传递。

14 hash.empty?

测试哈希是否为空(不包含键值对),返回truefalse

15

hash.fetch(key [,default])[或]

hash.fetch(key){| 关键| 块}

返回给定键的哈希如果无法找到,并且没有其他参数,则会引发IndexError异常; 如果给出默认值,则返回; 如果指定了可选块,则返回其结果。

16

hash.has_key?(key)[或] hash.include?(key)[or]

hash.key?(key)[或] hash.member?(key)

测试哈希中是否存在给定的,返回truefalse

17 hash.has_value?(value)

测试哈希是否包含给定的

18 hash.index(value)

返回为给定的哈希值,,如果没有匹配值被发现。

19 hash.indexes(键)

返回由给定键的值组成的新数组。将插入未找到的键的默认值。此方法已弃用。使用选择。

20 hash.indices(键)

返回由给定键的值组成的新数组。将插入未找到的键的默认值。此方法已弃用。使用选择。

21 hash.inspect

返回一个漂亮的打印字符string版本的哈希。

22 hash.invert

创建一个新的哈希哈希转换 ; 也就是说,在新的哈希中,来自哈希的键变为值和值成为键。

23 hash.keys

使用哈希值创建一个新数组

24 hash.length

以整数形式返回哈希的大小或长度

25

hash.merge(other_hash)[或]

hash.merge(other_hash){| key,oldval,newval | 块}

返回包含内容的新的哈希散列other_hash,哈希与那些重复键覆盖对other_hash

26

hash.merge!(other_hash)[或]

hash.merge!(other_hash){| key,oldval,newval | 块}

与合并相同,但更改已完成。

27 hash.rehash

根据每个的当前值重建散列如果值插入后,值已更改,则此方法重新索引哈希

28 hash.reject {| key,value | 块}

为每个创建一个新的哈希值,该块的计算结果为true

29 hash.reject!{| key,value | 块}

拒绝相同,但是改变了。

30 hash.replace(other_hash)

other_hash的内容替换哈希的内容

31 hash.select {| key,value | 块}

返回选自键-值对的新数组散列的量,返回

32 hash.shift

哈希中删除键值对,将其作为双元素数组返回。

33 hash.size

以整数形式返回哈希大小或长度

34 hash.sort

哈希转换为包含键值对数组的二维数组,然后将其排序为数组。

35 hash.store(key,value)

哈希中存储键值对

36 hash.to_a

从哈希创建一个二维数组。每个键/值对被转换为一个数组,所有这些数组都存储在一个包含的数组中。

37 hash.to_hash

返回hash(self)。

38 hash.to_s

哈希转换为数组,然后将该数组转换为字符string。

39

hash.update(other_hash)[或]

hash.update(other_hash){| key,oldval,newval | 块}

返回包含内容的新的哈希散列other_hash,在覆盖对哈希与那些重复键other_hash

40 hash.value?(value)

测试哈希是否包含给定的

41 哈希值

返回一个包含所有hash值的新数组

42 hash.values_at(obj,...)

返回一个包含与给定键或键相关联的哈希值的新数组

Ruby - 日期和时间

时间类表示日期和时间在Ruby中。它是操作系统提供的系统日期和时间功能的薄层。该课程可能无法在您的系统上表示1970年以前或2038年之后的日期。

本章让您熟悉日期和时间的所有最想要的概念。

获取当前日期和时间

以下是获取当前日期和时间的简单示例:

#!/usr/bin/ruby -w

time1 = Time.new

puts "Current Time : " + time1.inspect

# Time.now is a synonym:
time2 = Time.now
puts "Current Time : " + time2.inspect

输出结果如下 -

Current Time : Mon Jun 02 12:02:39 -0700 2008
Current Time : Mon Jun 02 12:02:39 -0700 2008

获取日期和时间的组件

我们可以使用Time对象来获取日期和时间的各种组件。以下是显示相同的例子 -

#!/usr/bin/ruby -w

time = Time.new

# Components of a Time
puts "Current Time : " + time.inspect
puts time.year    # => Year of the date 
puts time.month   # => Month of the date (1 to 12)
puts time.day     # => Day of the date (1 to 31 )
puts time.wday    # => 0: Day of week: 0 is Sunday
puts time.yday    # => 365: Day of year
puts time.hour    # => 23: 24-hour clock
puts time.min     # => 59
puts time.sec     # => 59
puts time.usec    # => 999999: microseconds
puts time.zone    # => "UTC": timezone name

输出结果如下 -

Current Time : Mon Jun 02 12:03:08 -0700 2008
2008
6
2
1
154
12
3
8
247476
UTC

Time.utc,Time.gm和Time.local函数

这两个函数可用于按照以下标准格式格式化日期:

# July 8, 2008
Time.local(2008, 7, 8)  
# July 8, 2008, 09:10am, local time
Time.local(2008, 7, 8, 9, 10)   
# July 8, 2008, 09:10 UTC
Time.utc(2008, 7, 8, 9, 10)  
# July 8, 2008, 09:10:11 GMT (same as UTC)
Time.gm(2008, 7, 8, 9, 10, 11)  

以下是以下列格式获取数组中的所有组件的示例:

[sec,min,hour,day,month,year,wday,yday,isdst,zone]

尝试以下 -

#!/usr/bin/ruby -w

time = Time.new

values = time.to_a
p values

输出结果如下 -

[26, 10, 12, 2, 6, 2008, 1, 154, false, "MST"]

该数组可以传递给Time.utcTime.local函数,以获取不同格式的日期如下:

#!/usr/bin/ruby -w

time = Time.new

values = time.to_a
puts Time.utc(*values)

输出结果如下 -

Mon Jun 02 12:15:36 UTC 2008

以下是从(依赖于平台的)时代以内部时间表示时间的方式 -

# Returns number of seconds since epoch
time = Time.now.to_i  

# Convert number of seconds into Time object.
Time.at(time)

# Returns second since epoch which includes microseconds
time = Time.now.to_f

时区和夏令时间

您可以使用Time对象获取有关Timezone的所有信息和夏令时如下:

time = Time.new

# Here is the interpretation
time.zone       # => "UTC": return the timezone
time.utc_offset # => 0: UTC is 0 seconds offset from UTC
time.zone       # => "PST" (or whatever your timezone is)
time.isdst      # => false: If UTC does not have DST.
time.utc?       # => true: if t is in UTC time zone
time.localtime  # Convert to local timezone.
time.gmtime     # Convert back to UTC.
time.getlocal   # Return a new Time object in local zone
time.getutc     # Return a new Time object in UTC

格式化时间和日期

有多种方式来格式化日期和时间。这是一个例子,显示几个 -

#!/usr/bin/ruby -w
time = Time.new

puts time.to_s
puts time.ctime
puts time.localtime
puts time.strftime("%Y-%m-%d %H:%M:%S")

输出结果如下 -

Mon Jun 02 12:35:19 -0700 2008
Mon Jun  2 12:35:19 2008
Mon Jun 02 12:35:19 -0700 2008
2008-06-02 12:35:19

时间格式化指令

下表中的这些指令与Time.strftime方法一起使用

没有 指令和说明
1 %一个

缩写的工作日名称(Sun)。

2 %一个

完整的工作日名称(星期日)。

3 %b

缩写月份名称(Jan)。

4 %B

全月份(1月)。

5 %C

优选的本地日期和时间表示。

6 %d

当天(01至31)。

7 %H

24小时营业时间(00至23点)。

8 %一世

一小时,12小时钟(01至12)。

9 %j

今年(001至366)。

10 %m

一月(01至12)。

11 %M

一小时(00至59)。

12 %p

经络指标(AM或PM)。

13 %S

二分钟(00至60分)。

14 %U

本周的周数,从第一个星期天开始,作为第一周的第一天(00到53)。

15 %W

本周的周数,从第一个星期一开始,作为第一周的第一天(00到53)。

16 %w

星期几(星期日为0,0至6)。

17 %X

唯一的日期优先代表,没有时间。

18 %X

唯一的优先代表,没有日期。

19 %y

一年没有一个世纪(00到99)。

20 %Y

年与世纪。

21 %Z

时区名称。

22 %%

字面%字符。

时间算术

您可以按照以下时间执行简单的运算:

now = Time.now           # Current time
puts now

past = now - 10          # 10 seconds ago. Time - number => Time
puts past

future = now + 10        # 10 seconds from now Time + number => Time
puts future

diff = future - now      # => 10  Time - Time => number of seconds
puts diff

输出结果如下 -

Thu Aug 01 20:57:05 -0700 2013
Thu Aug 01 20:56:55 -0700 2013
Thu Aug 01 20:57:15 -0700 2013
10.0

红宝石 - 范围

范围遍布各地:1月至12月,0至9,50至67行,依此类推。Ruby支持范围,并允许我们以各种方式使用范围 -

范围作为序列

第一个也许最自然的使用范围是表达一个序列。序列具有起始点,终点和在序列中产生连续值的方法。

Ruby使用""..""""...“范围运算符创建这些序列。双点格式创建一个包含范围,而三点形式创建一个排除指定高值的范围。

(1..5)        #==> 1, 2, 3, 4, 5
(1...5)       #==> 1, 2, 3, 4
("a".."d")    #==> "a", "b", "c", "d"

序列1..100被保持作为一个范围对象包含到两个引用Fixnum对象的对象。如果需要,您可以使用to_a方法将范围转换为列表尝试以下示例 -

#!/usr/bin/ruby

$, =", "   # Array value separator
range1 = (1..10).to_a
range2 = ("bar".."bat").to_a

puts "#{range1}"
puts "#{range2}"

输出结果如下 -

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
["bar", "bas", "bat"]

范围实现方法,让您迭代它们并以各种方式测试其内容 -

#!/usr/bin/ruby

# Assume a range
digits = 0..9

puts digits.include?(5)
ret = digits.min
puts "Min value is #{ret}"

ret = digits.max
puts "Max value is #{ret}"

ret = digits.reject {|i| i < 5 }
puts "Rejected values are #{ret}"

digits.each do |digit|
   puts "In Loop #{digit}"
end

输出结果如下 -

true
Min value is 0
Max value is 9
Rejected values are 5, 6, 7, 8, 9
In Loop 0
In Loop 1
In Loop 2
In Loop 3
In Loop 4
In Loop 5
In Loop 6
In Loop 7
In Loop 8
In Loop 9

范围作为条件

范围也可以用作条件表达式。例如,下面的代码片断打印设置从标准输入,其中,在每一组的第一行包含字线的开始和最后一行字结束 -

while gets
   print if /start/../end/
end

范例可用于案例陈述 -

#!/usr/bin/ruby

score = 70

result = case score
   when 0..40 then "Fail"
   when 41..60 then "Pass"
   when 61..70 then "Pass with Merit"
   when 71..100 then "Pass with Distinction"
   else "Invalid Score"
end

puts result

输出结果如下 -

Pass with Merit

范围作为间隔

多功能范围的最终用途是作为间隔测试:查看某些值是否落在由范围表示的间隔内。这是使用===,case等式运算符完成的。

#!/usr/bin/ruby

if ((1..10) === 5)
   puts "5 lies in (1..10)"
end

if (("a".."j") === "c")
   puts "c lies in ("a".."j")"
end

if (("a".."j") === "z")
   puts "z lies in ("a".."j")"
end

输出结果如下 -

5 lies in (1..10)
c lies in ("a".."j")

Ruby - 迭代器

迭代器只不过是集合支持的方法存储一组数据成员的对象称为集合。在Ruby中,数组和散列可以被称为集合。

迭代器一个接一个地返回一个集合的所有元素。我们将在这里探讨两个迭代器,每一个收集我们来看看这些细节。

Ruby每个迭代器

每个迭代器返回数组或散列的所有元素。

用法

collection.each do |variable|
   code
end

集合中的每个元素执行代码这里,collection可能是一个数组或一个ruby哈希。

#!/usr/bin/ruby

ary = [1,2,3,4,5]
ary.each do |i|
   puts i
end

输出结果如下 -

1
2
3
4
5

您总是将每个迭代器与一个块相关联。它将数组的每个值逐个返回到块。该值存储在变量i中,然后显示在屏幕上。

Ruby收集迭代器

收集迭代器返回一个集合中的所有元素。

用法

collection = collection.collect

收集方法不一定总是与块关联。收集方法返回整个集合,无论它是否是一个数组或散列。

#!/usr/bin/ruby

a = [1,2,3,4,5]
b = Array.new
b = a.collect
puts b

输出结果如下 -

1
2
3
4
5

注意 - collect方法不是在数组之间进行复制的正确方法。还有一种称为克隆的方法,它应该用于将一个数组复制到另一个数组中。

当您想要使用每个值进行某些操作以获取新数组时,通常使用collect方法。例如,该代码产生的数组b含有10倍的每个值一个

#!/usr/bin/ruby

a = [1,2,3,4,5]
b = a.collect{|x| 10*x}
puts b

输出结果如下 -

10
20
30
40
50

Ruby - 文件I / O

Ruby提供了一组在内核模块中实现的I / O相关方法。所有的I / O方法都是从IO类派生的。

IO提供了所有基本的方法,比如read,write,gets,puts,readline,getcprintf

本章将介绍Ruby中可用的所有基本I / O功能。有关更多功能,请参阅Ruby Class IO

投资报表

在前面的章节中,您已将值分配给变量,然后使用puts语句打印输出

语句指示程序显示存储在变量的值。这将在其写入的每一行的末尾添加一条新行。

#!/usr/bin/ruby

val1 = "This is variable one"
val2 = "This is variable two"
puts val1
puts val2

输出结果如下 -

This is variable one
This is variable two

获取声明

得到语句可用于采取从标准屏幕的用户称为STDIN任何输入。

以下代码显示如何使用gets语句。该代码将提示用户输入一个值,该值将存储在一个变量val中,最后将被打印在STDOUT上。

#!/usr/bin/ruby

puts "Enter a value :"
val = gets
puts val

输出结果如下 -

Enter a value :
This is entered value
This is entered value

putc声明

不同于整个字符string输出到屏幕上puts语句,putc语句可以一次输出一个字符。

以下代码的输出只是字符H -

#!/usr/bin/ruby

str = "Hello Ruby!"
putc str

输出结果如下 -

H

打印声明

打印语句是类似于声明。唯一的区别是,put语句在打印内容之后到下一行,而使用print语句,光标位于同一行上。

#!/usr/bin/ruby

print "Hello World"
print "Good Morning"

输出结果如下 -

Hello WorldGood Morning

打开和关闭文件

直到现在,您一直在读写标准的输入和输出。现在,我们将看到如何使用实际的数据文件。

File.new方法

您可以使用File.new方法创建一个File对象,用于读取,写入或两者,根据模式字符string。最后,您可以使用File.close方法关闭该文件。

用法

aFile = File.new("filename", "mode")
   # ... process the file
aFile.close

File.open方法

您可以使用File.open方法创建一个新的文件对象并将该文件对象分配给一个文件。然而,File.openFile.new方法之间有一个区别不同之处在于File.open方法可以与一个块相关联,而您不能使用File.new方法执行相同操作

File.open("filename", "mode") do |aFile|
   # ... process the file
end

阅读和写作文件

与“简单”I / O相同的方法可用于所有文件对象。所以,从标准输入中读取一行,并且aFile.gets从文件对象aFile读取一行。

然而,I / O对象提供了更多的访问方法,使我们的生活更轻松。

sysread方法

您可以使用sysread方法来读取文件的内容。当使用sysread方法时,您可以以任何模式打开文件。例如 -

以下是输入文本文件 -

This is a simple text file for testing purpose.

现在我们来试试看这个文件 -

#!/usr/bin/ruby

aFile = File.new("input.txt", "r")
if aFile
   content = aFile.sysread(20)
   puts content
else
   puts "Unable to open file!"
end

此语句将输出文件的前20个字符。文件指针现在将被放置在文件中的第21个字符。

syswrite方法

您可以使用syswrite方法将内容写入文件。在使用syswrite方法时,需要以写入方式打开文件。例如 -

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
else
   puts "Unable to open file!"
end

此语句将在文件中写入“ABCDEF”。

each_byte方法

此方法属于类File方法every_byte始终与块相关联。考虑下面的代码示例 -

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
   aFile.each_byte {|ch| putc ch; putc ?. }
else
   puts "Unable to open file!"
end

字符逐个传递给变量ch,然后如下显示在屏幕上 -

s. .a. .s.i.m.p.l.e. .t.e.x.t. .f.i.l.e. .f.o.r. .t.e.s.t.i.n.g. .p.u.r.p.o.s.e...
.
.

IO.readlines方法

File是类IO的子类。类IO也有一些可以用来操作文件的方法。

其中一种IO类方法是IO.readlines此方法逐行返回文件的内容。以下代码显示了使用IO.readlines的方法-

#!/usr/bin/ruby

arr = IO.readlines("input.txt")
puts arr[0]
puts arr[1]

在这段代码中,变量arr是一个数组。文件input.txt的每一行将是数组arr中的一个元素。因此,arr [0]将包含第一行,而arr [1]将包含该文件的第二行。

IO.foreach方法

此方法也逐行返回输出。方法foreach和方法readlines之间的区别在于方法foreach与块相关联。但是,与方法readlines不同foreach不会返回数组。例如 -

#!/usr/bin/ruby

IO.foreach("input.txt"){|block| puts block}

该代码将文件测试的内容逐行传递给可变块,然后输出将显示在屏幕上。

重命名和删除文件

您可以使用重命名删除方法以Ruby编程方式重命名和删除文件

以下是重命名现有文件test1.txt的示例 -

#!/usr/bin/ruby

# Rename a file from test1.txt to test2.txt
File.rename( "test1.txt", "test2.txt" )

以下是删除现有文件test2.txt的示例 -

#!/usr/bin/ruby

# Delete file test2.txt
File.delete("test2.txt")

文件模式和所有权

使用具有掩码chmod方法来更改文件的模式或权限/访问列表 -

以下是将现有文件test.txt的模式更改为掩码值的示例-

#!/usr/bin/ruby

file = File.new( "test.txt", "w" )
file.chmod( 0755 )

文件查询

以下命令测试在打开文件之前是否存在文件 -

#!/usr/bin/ruby

File.open("file.rb") if File::exists?( "file.rb" )

以下命令查询文件是否真的是一个文件 -

#!/usr/bin/ruby

# This returns either true or false
File.file?( "text.txt" ) 

以下命令查找给定的文件名是否为目录 -

#!/usr/bin/ruby

# a directory
File::directory?( "/usr/local/bin" ) # => true

# a file
File::directory?( "file.rb" ) # => false

以下命令查找文件是否可读,可写或可执行 -

#!/usr/bin/ruby

File.readable?( "test.txt" )   # => true
File.writable?( "test.txt" )   # => true
File.executable?( "test.txt" ) # => false

以下命令查找该文件是否为零大小 -

#!/usr/bin/ruby

File.zero?( "test.txt" )      # => true

以下命令返回文件的大小 -

#!/usr/bin/ruby

File.size?( "text.txt" )     # => 1002

以下命令可用于找出一种文件类型 -

#!/usr/bin/ruby

File::ftype( "test.txt" )     # => file

ftype方法通过返回以下文件,文件,目录,characterSpecial,blockSpecial,fifo,link,socket或unknown来识别文件的类型。

以下命令可用于查找文件何时创建,修改或上次访问 -

#!/usr/bin/ruby

File::ctime( "test.txt" ) # => Fri May 09 10:06:37 -0700 2008
File::mtime( "text.txt" ) # => Fri May 09 10:44:44 -0700 2008
File::atime( "text.txt" ) # => Fri May 09 10:45:01 -0700 2008

Ruby中的目录

所有文件都包含在各种目录中,而Ruby也没有处理这些问题。File类处理文件,目录使用Dir来处理

浏览目录

要更改Ruby程序中的目录,请使用Dir.chdir,如下所示。此示例将当前目录更改为/ usr / bin

Dir.chdir("/usr/bin")

你可以找到目前的目录与Dir.pwd -

puts Dir.pwd # This will return something like /usr/bin

您可以使用Dir.entries获取特定目录中的文件和目录列表-

puts Dir.entries("/usr/bin").join(" ")

Dir.entries返回一个包含指定目录中所有条目的数组。Dir.foreach提供了相同的功能 -

Dir.foreach("/usr/bin") do |entry|
   puts entry
end

更简洁的获取目录列表的方法是使用Dir的类数组方法 -

Dir["/usr/bin/*"]

创建目录

Dir.mkdir可以用来创建目录-

Dir.mkdir("mynewdir")

您还可以使用mkdir为新目录(不是已存在的目录)设置权限 -

注意 - 掩码755将权限所有者,组,世界[任何人]设置为rwxr-xr-x,其中r = read,w = write和x = execute。

Dir.mkdir( "mynewdir", 755 )

删除目录

Dir.delete可以用来删除目录。Dir.unlinkDir.rmdir执行完全相同的功能,并提供了方便。

Dir.delete("testdir")

创建文件和临时目录

临时文件是在程序执行期间可能会短暂创建的文件,但不是永久性的信息存储。

Dir.tmpdir提供了当前系统上临时目录的路径,尽管默认情况下该方法不可用。为了使Dir.tmpdir可用,有必要使用require"tmpdir"。

您可以使用Dir.tmpdirFile.join来创建一个独立于平台的临时文件 -

require "tmpdir"
   tempfilename = File.join(Dir.tmpdir, "tingtong")
   tempfile = File.new(tempfilename, "w")
   tempfile.puts "This is a temporary file"
   tempfile.close
   File.delete(tempfilename)

此代码创建一个临时文件,向其中写入数据并将其删除。Ruby的标准库中还包括一个名为库将它视为可以为您创建临时文件-

require "tempfile"
   f = Tempfile.new("tingtong")
   f.puts "Hello"
   puts f.path
   f.close

内置功能

这里是用于处理文件和目录的ruby内置函数 -

Ruby - 异常

执行和异常总是在一起。如果您打开的文件不存在,那么如果您没有正确处理这种情况,那么您的程序被认为是质量差的。

如果发生异常,程序将停止。因此,异常用于处理可能在程序执行期间发生的各种类型的错误,并采取适当的措施,而不是完全停止程序。

Ruby提供了一个很好的机制来处理异常。我们包含可能在开始/结束中引发异常的代码,并使用rescue子句来告诉Ruby我们要处理的异常类型。

用法

begin  
# -  
rescue OneTypeOfException  
# -  
rescue AnotherTypeOfException  
# -  
else  
# Other exceptions
ensure
# Always will be executed
end

开始救援的一切都受到保护。如果在执行该代码块期间发生异常,则控制将传递到在rescueend之间的块

对于begin中的每个rescue子句,Ruby会依次对比引用的异常与每个参数。如果rescue子句中命名的异常与当前抛出的异常的类型相同,或者是异常的超类,则匹配将成功。

在异常与指定的任何错误类型不匹配的情况下,我们允许在所有rescue子句之后使用else子句

#!/usr/bin/ruby

begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "
"

输出结果如下。您可以看到STDIN被替换为文件,因为打开失败。

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

使用retry语句

您可以使用rescue捕获异常,然后使用retry语句从头开始执行begin块。

用法

begin
   # Exceptions raised by this code will 
   # be caught by the following rescue clause
rescue
   # This block will capture all types of exceptions
   retry  # This will move control to the beginning of begin
end

#!/usr/bin/ruby

begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
   fname = "existant_file"
   retry
end

以下是流程的流程 -

- 请注意,如果重新替换的名称的文件不存在,则此示例代码将无限次重试。如果您使用重试进行异常处理,请小心

使用raise语句

您可以使用raise语句来引发异常。以下方法会在调用时引发异常。这是第二条消息将被打印出来。

用法

raise 

OR

raise "Error Message" 

OR

raise ExceptionType, "Error Message"

OR

raise ExceptionType, "Error Message" condition

第一种形式只是重新引发当前的异常(如果没有当前的异常,则是RuntimeError)。这在异常处理程序中使用,需要在传递异常处理程序之前拦截异常。

第二种形式创建一个新的RuntimeError异常,将其消息设置为给定的字符string。然后,这个异常被提升为调用堆栈。

第三个表单使用第一个参数创建一个异常,然后将关联的消息设置为第二个参数。

第四种形式与第三种形式相似,但您可以添加任何条件语句,除非引发异常。

#!/usr/bin/ruby

begin  
   puts "I am before the raise."  
   raise "An error has occurred."  
   puts "I am after the raise."  
rescue  
   puts "I am rescued."  
end  
puts "I am after the begin block."  

输出结果如下 -

I am before the raise.  
I am rescued.  
I am after the begin block.  

另外一个例子显示了加注的用法-

#!/usr/bin/ruby

begin  
   raise "A test exception."  
rescue Exception => e  
   puts e.message  
   puts e.backtrace.inspect  
end  

输出结果如下 -

A test exception.
["main.rb:4"]

使用确认声明

有时候,您需要保证在代码块结束时进行一些处理,无论是否引发异常。例如,您可能有一个文件打开,进入该块,并且您需要确保它在块退出时关闭。

保证条款不只是这个。确保在最后一个救援条款之后,并包含一段代码,该块代码将随着块终止而始终执行。如果块正常退出,如果它引发和拯救异常,或者如果被未捕获的异常终止,则确保块将被运行,这并不重要

用法

begin 
   #.. process 
   #..raise exception
rescue 
   #.. handle error 
ensure 
   #.. finally ensure execution
   #.. This will always execute.
end

begin
   raise "A test exception."
rescue Exception => e
   puts e.message
   puts e.backtrace.inspect
ensure
   puts "Ensuring execution"
end

输出结果如下 -

A test exception.
["main.rb:4"]
Ensuring execution

使用else语句

如果else子句存在,则遵循救援条款和任何确认

一个身体否则只有在没有异常是由代码的主体提出的条款执行。

用法

begin 
   #.. process 
   #..raise exception
rescue 
   # .. handle error
else
   #.. executes if there is no exception
ensure 
   #.. finally ensure execution
   #.. This will always execute.
end

begin
   # raise "A test exception."
   puts "I"m not raising exception"
rescue Exception => e
   puts e.message
   puts e.backtrace.inspect
else
   puts "Congratulations-- no errors!"
ensure
   puts "Ensuring execution"
end

输出结果如下 -

I"m not raising exception
Congratulations-- no errors!
Ensuring execution

引发的错误信息可以使用$!变量。

抓住和投掷

虽然提升和救援的例外机制对于在出现问题时放弃执行是伟大的,但是在正常处理期间能够跳出一些深入嵌套的构造有时是很好的。这是抓住和抛出来派上用场的地方。

捕获限定了标记的具有给定名称(其可以是符号或字符string)的块。块正常执行,直到遇到一个投掷。

用法

throw :lablename
#.. this will not be executed
catch :lablename do
#.. matching catch will be executed after a throw is encountered.
end

OR

throw :lablename condition
#.. this will not be executed
catch :lablename do
#.. matching catch will be executed after a throw is encountered.
end

以下示例使用throw来终止与用户的交互,如果“!” 是响应任何提示输入。

def promptAndGet(prompt)
   print prompt
   res = readline.chomp
   throw :quitRequested if res == "!"
   return res
end

catch :quitRequested do
   name = promptAndGet("Name: ")
   age = promptAndGet("Age: ")
   sex = promptAndGet("Sex: ")
   # ..
   # process information
end
promptAndGet("Name:")

您应该在机器上尝试上述程序,因为它需要手动交互。输出结果如下 -

Name: Ruby on Rails
Age: 3
Sex: !
Name:Just Ruby

类异常

Ruby的标准类和模块引发异常。所有的异常类都形成一个层次结构,其顶层有Exception类。下一级包含七种不同的类型 -

在这个级别还有一个例外,Fatal,但Ruby解释器只在内部使用。

ScriptError和StandardError都有多个子类,但是我们不需要在这里详细介绍。重要的是,如果我们创建我们自己的异常类,它们需要是类Exception或其后代之一的子类。

我们来看一个例子 -

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason = reason
   end
end

现在,看下面的例子,这将使用这个异常 -

File.open(path, "w") do |file|
begin
   # Write out the data ...
rescue
   # Something went wrong!
   raise FileSaveError.new($!)
end
end

这里重要的一点是提高FileSaveError.new($!)我们调用raise来表示发生了异常,传递一个新的FileSaveError实例,原因是特定的异常导致数据写入失败。

Ruby - 面向对象

Ruby是一种纯粹的面向对象的语言,Ruby都是一个对象。Ruby中的每个值都是一个对象,即使是最原始的东西:字符string,数字甚至是真假。即使是一个类本身是一个对象是所述的实例类。本章将介绍与面向对象Ruby相关的所有主要功能。

一个类用于指定一个对象的形式,它将数据表示和方法结合起来,将数据操作成一个整齐的包。类中的数据和方法称为类的成员。

Ruby类定义

定义类时,可以为数据类型定义蓝图。这实际上并不定义任何数据,但它确实定义了类名称是什么意思,也就是说,类的对象将由哪个对象组成,哪些操作可以在这样的对象上执行。

类定义从关键字开始,后跟类名称,并以结尾分隔例如,我们使用关键字类定义了Box类,如下所示:

class Box
   code
end

名称必须以大写字母开头,并且包含多个单词的约定名称与每个大写字母一起运行,没有分隔符(CamelCase)。

定义Ruby对象

一个类提供了对象的蓝图,所以基本上从一个类创建一个对象。我们使用new关键字声明类的对象以下语句声明类Box的两个对象 -

box1 = Box.new
box2 = Box.new

初始化方法

initialize方法是一个标准的Ruby类方法和工作方式几乎相同的方式,构造函数在其他面向对象编程语言的作品。当您要在创建对象时初始化一些类变量时,initialize方法很有用。这个方法可能需要一个参数列表,像其他的ruby方法一样,它将在之前的def关键字如下所示:

class Box
   def initialize(w,h)
      @width, @height = w, h
   end
end

实例变量

实例变量是一种类属性的,他们就成为对象的属性一旦被使用类创建的对象。每个对象的属性都被单独分配,与其他对象不共享任何值。它们使用类中的@运算符进行访问,但是在使用公共方法的类之外访问它们,这些方法称为访问器方法如果我们采用上面定义的类Box,那么@width和@height是类Box的实例变量。

class Box
   def initialize(w,h)
      # assign instance variables
      @width, @height = w, h
   end
end

访问者和设置者方法

为了使变量从类外部可用,它们必须在访问器方法定义,这些访问器方法也称为getter方法。以下示例显示了访问器方法的用法 -

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # accessor methods
   def printWidth
      @width
   end

   def printHeight
      @height
   end
end

# create an object
box = Box.new(10, 20)

# use accessor methods
x = box.printWidth()
y = box.printHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"

当执行上述代码时,输出结果如下-

Width of the box is : 10
Height of the box is : 20

类似于访问方法,用于访问变量的值,Ruby提供了一种使用setter方法从类外部设置这些变量的值的方法,定义如下:

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # accessor methods
   def getWidth
      @width
   end
   def getHeight
      @height
   end

   # setter methods
   def setWidth=(value)
      @width = value
   end
   def setHeight=(value)
      @height = value
   end
end

# create an object
box = Box.new(10, 20)

# use setter methods
box.setWidth = 30
box.setHeight = 50

# use accessor methods
x = box.getWidth()
y = box.getHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"

当执行上述代码时,输出结果如下-

Width of the box is : 30
Height of the box is : 50

实例方法

实例方法中以相同的方式也被定义为我们定义使用任何其它方法DEF关键字和它们只能使用一个类的实例如下所示来使用。它们的功能不限于访问实例变量,而且还可以根据您的要求进行更多操作。

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# create an object
box = Box.new(10, 20)

# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"

当执行上述代码时,输出结果如下-

Area of the box is : 200

类方法和变量

类变量是一个变量,它是一个类的所有实例之间共享。换句话说,有一个变量的实例,它被对象实例访问。类变量前面加上两个@字符(@@)。类变量必须在类定义内初始化,如下所示。

使用def self.methodname()定义类方法,该方法以末尾分隔符结尾,并使用类名称作为classname.methodname调用,如以下示例所示 -

#!/usr/bin/ruby -w

class Box
   # Initialize our class variables
   @@count = 0
   def initialize(w,h)
      # assign instance avriables
      @width, @height = w, h

      @@count += 1
   end

   def self.printCount()
      puts "Box count is : #@@count"
   end
end

# create two object
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)

# call class method to print box count
Box.printCount()

当执行上述代码时,输出结果如下-

Box count is : 2

to_s方法

您定义的任何类都应该有一个to_s实例方法来返回对象的字符string表示形式。以下是一个简单的例子来表示一个Box对象的宽度和高度 -

#!/usr/bin/ruby -w

class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # define to_s method
   def to_s
      "(w:#@width,h:#@height)"  # string formatting of the object.
   end
end

# create an object
box = Box.new(10, 20)

# to_s method will be called in reference of string automatically.
puts "String representation of box is : #{box}"

当执行上述代码时,输出结果如下-

String representation of box is : (w:10,h:20)

访问控制

Ruby在实例方法级别提供三级保护,可能是公共的,私有的或受保护的Ruby不对实例和类变量应用任何访问控制。

以下是一个简单的示例来显示所有三个访问修饰符的语法 -

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # instance method by default it is public
   def getArea
      getWidth() * getHeight
   end

   # define private accessor methods
   def getWidth
      @width
   end
   def getHeight
      @height
   end
   # make them private
   private :getWidth, :getHeight

   # instance method to print area
   def printArea
      @area = getWidth() * getHeight
      puts "Big box area is : #@area"
   end
   # make it protected
   protected :printArea
end

# create an object
box = Box.new(10, 20)

# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"

# try to call protected or methods
box.printArea()

当执行上述代码时,会产生以下结果。这里,第一种方法被称为成功,但第二种方法给了一个问题。

Area of the box is : 200
test.rb:42: protected method `printArea" called for #
<Box:0xb7f11280 @height = 20, @width = 10> (NoMethodError)

类继承

面向对象编程中最重要的概念之一是继承。继承允许我们根据另一个类定义一个类,这样可以更容易地创建和维护应用程序。

继承还提供了重用代码功能和快速实施时间的机会,但不幸的是,Ruby不支持多级继承,而Ruby支持mixinsmixin就像多继承的专门实现,只有接口部分被继承。

当创建一个类时,程序员可以指定新类应该继承现有类的成员,而不是编写全新的数据成员和成员函数。这个现有的类称为基类或超类,新类称为派生类或子类

Ruby还支持子类化的概念,即继承,下面的例子解释了这个概念。扩展类的语法很简单。只需添加一个<character和超类的名称到你的class语句。例如,下面将一个类BigBox定义Box的子类-

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# define a subclass
class BigBox < Box

   # add a new instance method
   def printArea
      @area = @width * @height
      puts "Big box area is : #@area"
   end
end

# create an object
box = BigBox.new(10, 20)

# print the area
box.printArea()

当执行上述代码时,输出结果如下-

Big box area is : 200

方法覆盖

虽然您可以在派生类中添加新功能,但有时您希望更改父类中已定义方法的行为。您可以简单地通过保持方法名称相同,并覆盖方法的功能,如下例所示:

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# define a subclass
class BigBox < Box

   # change existing getArea method as follows
   def getArea
      @area = @width * @height
      puts "Big box area is : #@area"
   end
end

# create an object
box = BigBox.new(10, 20)

# print the area using overriden method.
box.getArea()

运算符重载

我们希望+运算符使用+执行两个Box对象的向量加法,*运算符将Box的宽度和高度乘以一个标量,一元运算符来否定Box的宽度和高度。这里是一个具有数学运算符定义的Box类的版本 -

class Box
   def initialize(w,h) # Initialize the width and height
      @width,@height = w, h
   end

   def +(other)         # Define + to do vector addition
      Box.new(@width + other.width, @height + other.height)
   end

   def -@               # Define unary minus to negate width and height
      Box.new(-@width, -@height)
   end

   def *(scalar)        # To perform scalar multiplication
      Box.new(@width*scalar, @height*scalar)
   end
end

冻结物体

有时,我们想防止对象被更改。Object中的冻结方法允许我们这样做,有效地将对象变成一个常量。任何对象都可以通过调用Object.freeze来冻结冻结对象可能不被修改:您不能更改其实例变量。

您可以使用Object.frozen检查给定对象是否已被冻结方法,如果对象被冻结,返回true,否则返回false值。以下示例清除概念 -

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # accessor methods
   def getWidth
      @width
   end
   def getHeight
      @height
   end

   # setter methods
   def setWidth=(value)
      @width = value
   end
   def setHeight=(value)
      @height = value
   end
end

# create an object
box = Box.new(10, 20)

# let us freez this object
box.freeze
if( box.frozen? )
   puts "Box object is frozen object"
else
   puts "Box object is normal object"
end

# now try using setter methods
box.setWidth = 30
box.setHeight = 50

# use accessor methods
x = box.getWidth()
y = box.getHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"

当执行上述代码时,输出结果如下-

Box object is frozen object
test.rb:20:in `setWidth=": can"t modify frozen object (TypeError)
   from test.rb:39

类常数

您可以通过将直接数字或字符string值分配给变量来定义类中的常量,该变量定义为不使用@或@@。按照惯例,我们保持常数名字大写。

一旦定义了一个常量,你不能改变它的值,但你可以直接在一个类中直接访问一个变量,就像一个变量一样,但是如果你想访问类之外的一个常量,那么你必须使用classname :: constant,如下面的例子。

#!/usr/bin/ruby -w

# define a class
class Box
   BOX_COMPANY = "TATA Inc"
   BOXWEIGHT = 10
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# create an object
box = Box.new(10, 20)

# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"
puts Box::BOX_COMPANY
puts "Box weight is: #{Box::BOXWEIGHT}"

当执行上述代码时,输出结果如下-

Area of the box is : 200
TATA Inc
Box weight is: 10

类常量是继承的,可以像实例方法一样被覆盖。

使用分配创建对象

当您想要创建一个对象而不调用其构造函数初始化即使用新方法时,可能会出现这种情况,在这种情况下,您可以调用allocate,这将为您创建一个未初始化的对象,如下例所示:

#!/usr/bin/ruby -w

# define a class
class Box
   attr_accessor :width, :height

   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # instance method
   def getArea
      @width * @height
   end
end

# create an object using new
box1 = Box.new(10, 20)

# create another object using allocate
box2 = Box.allocate

# call instance method using box1
a = box1.getArea()
puts "Area of the box is : #{a}"

# call instance method using box2
a = box2.getArea()
puts "Area of the box is : #{a}"

当执行上述代码时,输出结果如下-

Area of the box is : 200
test.rb:14: warning: instance variable @width not initialized
test.rb:14: warning: instance variable @height not initialized
test.rb:14:in `getArea": undefined method `*" 
   for nil:NilClass (NoMethodError) from test.rb:29

类信息

如果类定义是可执行代码,这意味着它们在某个对象的上下文中执行:self必须引用某些对象。我们来看看它是什么

#!/usr/bin/ruby -w

class Box
   # print class information
   puts "Type of self = #{self.type}"
   puts "Name of self = #{self.name}"
end

当执行上述代码时,输出结果如下-

Type of self = Class
Name of self = Box

这意味着使用该类作为当前对象执行类定义。这意味着在执行方法定义时,元类及其超类中的方法将可用。

Ruby - 正则表达式

一个正则表达式是一个字符的特殊序列,可帮助您匹配或查找使用的模式举办了专门的语法其他字符string或字符string集。

正则表达式文本是斜线之间或任意分隔符接着%R如下之间的图案-

用法

/pattern/
/pattern/im    # option can be specified
%r!/usr/local! # general delimited regular expression

#!/usr/bin/ruby

line1 = "Cats are smarter than dogs";
line2 = "Dogs also like meat";

if ( line1 =~ /Cats(.*)/ )
   puts "Line1 contains Cats"
end
if ( line2 =~ /Cats(.*)/ )
   puts "Line2 contains  Dogs"
end

输出结果如下 -

Line1 contains Cats

正则表达式修饰符

正则表达式文字可能包含一个可选修饰符,用于控制匹配的各个方面。修饰符在第二个斜杠字符之后指定,如前所示,可以由以下字符之一表示 -

没有 修饰和说明
1 一世

忽略匹配文本时的情况。

2 o

执行#{}插值仅一次,第一次对正则表达式文字进行评估。

3 X

忽略空格,并允许在正则表达式中的注释。

4 m

匹配多行,将换行符识别为常规字符。

5 u,e,s,n

将正则表达式解释为Unicode(UTF-8),EUC,SJIS或ASCII。如果没有指定这些修饰符,则假定正则表达式使用源编码。

像使用%Q分隔的字符string文字,Ruby允许您使用%r开始正则表达式,然后是您选择的分隔符。当您描述的模式包含许多您不想逃脱的正斜杠字符时,这很有用

# Following matches a single slash character, no escape required
%r|/|               

# Flag characters are allowed with this syntax, too
%r[</(.*)>]i  

规则表达模式

除了控制字符(+?。* ^ $()[] {} | ),所有字符都与其自身匹配。您可以通过使用反斜杠将其转换为控制字符。

正则表达式示例

搜索和替换

一些使用正则表达式的最重要的String方法是subgsub,它们的就地变体sub!gsub!

所有这些方法使用Regexp模式执行搜索和替换操作。子!替换第一次出现的模式和gsubgsub!取代所有事件。

GSUB返回一个新字符string,离开原来的地方未修改作为子!gsub!修改它们被调用的字符string。

以下是这个例子 -

#!/usr/bin/ruby

phone = "2004-959-559 #This is Phone Number"

# Delete Ruby-style comments
phone = phone.sub!(/#.*$/, "")   
puts "Phone Num : #{phone}"

# Remove anything other than digits
phone = phone.gsub!(/D/, "")    
puts "Phone Num : #{phone}"

输出结果如下 -

Phone Num : 2004-959-559
Phone Num : 2004959559

以下是另一个例子 -

#!/usr/bin/ruby

text = "rails are rails, really good Ruby on Rails"

# Change "rails" to "Rails" throughout
text.gsub!("rails", "Rails")

# Capitalize the word "Rails" throughout
text.gsub!(/rails/, "Rails")

puts "#{text}"

输出结果如下 -

Rails are Rails, really good Ruby on Rails

Ruby / DBI教程

本章教你如何使用Ruby访问数据库。红宝石DBI模块提供类似于Perl DBI模块的Ruby脚本独立于数据库的接口。

DBI代表Ruby的数据库独立接口,这意味着DBI在Ruby代码和底层数据库之间提供了一个抽象层,使您可以轻松地切换数据库实现。它定义了一组方法,变量和约定,提供一致的数据库接口,与实际使用的数据库无关。

DBI可以与以下接口连接 -

DBI应用程序的体系结构

DBI独立于后端中可用的任何数据库。您可以使用DBI,无论您是使用Oracle,MySQL还是Informix等。从以下体系结构图中可以清楚看出。

Ruby DBI架构

Ruby DBI的一般架构使用两层 -

学习提醒

如果要编写Ruby脚本来访问MySQL数据库,则需要安装Ruby MySQL模块。

该模块作为DBD,如上所述,可从https://www.tmtm.org/en/mysql/ruby/下载

获取和安装Ruby / DBI

您可以从以下位置下载并安装Ruby DBI模块 -

http://rubyforge.org/projects/ruby-dbi/

在开始此安装之前,请确保您具有root权限。现在,按照下面给出的步骤 -

步骤1

$ tar zxf dbi-0.2.0.tar.gz

第2步

进入分发目录dbi-0.2.0 nd,然后使用该目录中setup.rb脚本进行配置。最通用的配置命令如下,配置参数后面没有参数。默认情况下,此命令配置分发以安装所有驱动程序。

$ ruby setup.rb config

更具体地说,提供--with选项,列出您要使用的分发的特定部分。例如,仅配置主DBI模块和MySQL DBD级别驱动程序,请执行以下命令 -

$ ruby setup.rb config --with = dbi,dbd_mysql

步骤3

最后一步是创建驱动程序并使用以下命令进行安装 -

$ ruby setup.rb setup
$ ruby setup.rb install

数据库连接

假设我们要使用MySQL数据库,在连接到数据库之前,请确保以下内容 -

以下是与MySQL数据库“TESTDB”连接的示例

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   # get server version string and display it
   row = dbh.select_one("SELECT VERSION()")
   puts "Server version: " + row[0]
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

在运行此脚本时,它会在我们的Linux机器上产生以下结果。

Server version: 5.0.45

如果使用数据源建立连接,则会返回数据库句柄并将其保存到dbh中以供进一步使用,否则dbh设置为nil值,e.erre :: errstr分别返回错误代码和错误字符string。

最后,在出来之前,确保数据库连接关闭,资源释放。

插入操作

当您要将记录创建到数据库表中时,需要执行INSERT操作。

建立数据库连接后,我们可以使用do方法或prepareexecute方法将表或记录创建到数据库表中

使用do语句

不返回行的语句可以通过调用do数据库句柄方法来发出此方法接受一个语句string参数,并返回受该语句影响的行数的计数。

dbh.do("DROP TABLE IF EXISTS EMPLOYEE")
dbh.do("CREATE TABLE EMPLOYEE (
   FIRST_NAME  CHAR(20) NOT NULL,
   LAST_NAME  CHAR(20),
   AGE INT,  
   SEX CHAR(1),
   INCOME FLOAT )" );

类似地,您可以执行SQL INSERT语句以在EMPLOYEE表中创建记录。

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   dbh.do( "INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME)
         VALUES ("Mac", "Mohan", 20, "M", 2000)" )
   puts "Record has been created"
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

使用准备和执行

您可以使用DBI类的prepareexecute方法通过Ruby代码执行SQL语句。

记录创建需要以下步骤:

以下是使用这两种方法的语法 -

sth = dbh.prepare(statement)
sth.execute
   ... zero or more SQL operations ...
sth.finish

这两种方法可用于将绑定传递给SQL语句。可能会提前输入要输入的值的情况。在这种情况下,使用结合值。使用问号()代替实际值,然后通过execute()API传递实际值。

以下是在EMPLOYEE表中创建两个记录的示例 -

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare( "INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME)
         VALUES (?, ?, ?, ?, ?)" )
   sth.execute("John", "Poul", 25, "M", 2300)
   sth.execute("Zara", "Ali", 17, "F", 1000)
   sth.finish
   dbh.commit
   puts "Record has been created"
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

如果一次有多个INSERT,那么首先准备一个语句,然后在循环中多次执行一个语句比每次循环调用更有效。

阅读操作

任何数据库上的READ操作意味着从数据库中获取一些有用的信息。

一旦建立了数据库连接,我们就可以对这个数据库进行查询了。我们可以使用do方法或准备执行方法从数据库表中获取值。

记录提取需要以下步骤 -

以下是从薪水超过1000的EMPLOYEE表中查询所有记录的过程。

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare("SELECT * FROM EMPLOYEE WHERE INCOME > ?")
   sth.execute(1000)

   sth.fetch do |row|
   printf "First Name: %s, Last Name : %s
", row[0], row[1]
   printf "Age: %d, Sex : %s
", row[2], row[3]
   printf "Salary :%d 

", row[4]
end
   sth.finish
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

输出结果如下 -

First Name: Mac, Last Name : Mohan
Age: 20, Sex : M
Salary :2000

First Name: John, Last Name : Poul
Age: 25, Sex : M
Salary :2300

从数据库中获取记录的方法有更多。如果您有兴趣,请通过提取结果,否则请继续下一节。

更新操作

UPDATE对任何数据库的操作意味着更新数据库中已有的一个或多个记录。以下是将SEX的所有记录更新为“M”的过程。在这里,我们将所有男性的年龄增加一年。这将需要三个步骤 -

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare("UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = ?")
   sth.execute("M")
   sth.finish
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

删除操作

当您要从数据库中删除一些记录时,需要执行DELETE操作。以下是从EMPLOYEE中删除AGE超过20的所有记录的过程。此操作将执行以下步骤。

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare("DELETE FROM EMPLOYEE WHERE AGE > ?")
   sth.execute(20)
   sth.finish
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

执行事物

事务是确保数据一致性的一种机制。事物应具有以下四个属性 -

DBI提供两种提交回滚事务的方法。还有一种称为事务的方法可用于实现事务。实施事物有两种简单的方法 -

接近我

第一种方法使用DBI的提交回滚方法显式提交或取消事务 -

dbh["AutoCommit"] = false # Set auto commit to false.
begin
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "John"")
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "Zara"")
   dbh.commit
rescue
   puts "transaction failed"
   dbh.rollback
end
dbh["AutoCommit"] = true

方法二

第二种方法使用事务方法。这更简单,因为它需要一个包含构成事务的语句的代码块。事物方法执行块,然后调用提交回滚自动,这取决于该块是否成功或失败-

dbh["AutoCommit"] = false # Set auto commit to false.
dbh.transaction do |dbh|
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "John"")
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = "Zara"")
end
dbh["AutoCommit"] = true

COMMIT操作

提交是操作,它给数据库提供一个绿色信号来完成更改,并且在此操作之后,没有更改可以恢复。

这是一个简单的例子来调用commit方法。

dbh.commit

ROLLBACK操作

如果您对一个或多个更改不满意,并且要完全还原这些更改,请使用回滚方法。

这是一个简单的例子来调用回滚方法。

dbh.rollback

断开数据库

要断开数据库连接,请使用disconnect API。

dbh.disconnect

如果与数据库的连接由用户断开连接方法关闭,任何未完成的事务将由DBI回滚。然而,而不是依赖于DBI的任何实现细节,您的应用程序将更好地明确地调用提交或回滚。

处理错误

有很多错误来源。一些示例是执行的SQL语句中的语法错误,连接失败或为已取消或已完成的语句句柄调用fetch方法。

如果DBI方法失败,DBI会引发异常。DBI方法可能引发几种类型的异常,但是两个最重要的异常类是DBI :: InterfaceErrorDBI :: DatabaseError

这些类的异常对象有三个名为errerrstrstate的属性,它们表示错误号,描述性错误字符string和标准错误代码。属性如下所示 -

在大多数示例中,您已经看到以下代码:

rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

要获取关于脚本在执行过程中执行的操作的调试信息,可以启用跟踪。为此,您必须首先加载dbi / trace模块,然后调用跟踪方式来控制跟踪模式并输出目标 -

require "dbi/trace"
..............

trace(mode, destination)

模式值可以为0(关闭),1,2或3,目的地应为IO对象。默认值分别为2和STDERR。

代码块与方法

有一些方法可以创建句柄。可以使用代码块调用这些方法。使用代码块和方法的优点是它们将代码块的句柄提供为其参数,并在块终止时自动清除句柄。有几个例子来理解这个概念。

实施例1

DBI.connect可以采取代码块,将数据库句柄传递给它,并自动断开块末尾的句柄,如下所示。

dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") do |dbh|

实施例2

dbh.prepare可以采取代码块,将语句句柄传递给它,并在块的结尾自动调用finish,如下所示。

dbh.prepare("SHOW DATABASES") do |sth|
   sth.execute
   puts "Databases: " + sth.fetch_all.join(", ")
end

实施例3

dbh.execute可以采取代码块,将语句句柄传递给它,并在块的结尾自动调用finish,如下所示:

dbh.execute("SHOW DATABASES") do |sth|
   puts "Databases: " + sth.fetch_all.join(", ")
end

DBI 事务方法也采用上面已经描述的代码块。

驱动程序特定功能和属性

DBI允许数据库驱动程序提供额外的特定于数据库的功能,用户可以通过任何Handle对象func方法调用该函数

支持特定于驱动程序的属性,可以使用[] =[]方法进行设置或获取

#!/usr/bin/ruby

require "dbi"
begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") 
   puts dbh.func(:client_info)
   puts dbh.func(:client_version)
   puts dbh.func(:host_info)
   puts dbh.func(:proto_info)
   puts dbh.func(:server_info)
   puts dbh.func(:thread_id)
   puts dbh.func(:stat)
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
ensure
   dbh.disconnect if dbh
end

输出结果如下 -

5.0.45
50045
Localhost via UNIX socket
10
5.0.45
150621
Uptime: 384981  Threads: 1  Questions: 1101078  Slow queries: 4 
Opens: 324  Flush tables: 1  Open tables: 64  
Queries per second avg: 2.860

Ruby Web应用程序 - CGI编程

Ruby是一种通用语言; 它根本不能被称为网络语言即使如此,一般来说,Web应用程序和Web工具是Ruby最常用的功能之一。

您不仅可以在Ruby中编写自己的SMTP服务器,FTP守护程序或Web服务器,还可以使用Ruby进行更常用的工作,如CGI编程或替代PHP。

请使用CGI编程教程花费几分钟时间了解CGI编程的更多细节。

编写CGI脚本

最基本的Ruby CGI脚本看起来像这样 -

#!/usr/bin/ruby

puts "HTTP/1.0 200 OK"
puts "Content-type: text/html

"
puts "<html><body>This is a test</body></html>"

如果您调用此脚本test.cgi并将其上传到具有正确权限的基于Unix的Web托管服务提供商,则可以将其用作CGI脚本。

例如,如果您使用网站https://www.example.com/托管一个Linux Web托管服务提供商,并将test.cgi上传到主目录并赋予其执行权限,然后访问https:// www。 example.com/test.cgi应该返回一个HTML页面,说这是一个测试

这里当从Web浏览器请求test.cgi时,Web服务器在Web站点上查找test.cgi,然后使用Ruby解释器执行。Ruby脚本返回一个基本的HTTP头,然后返回一个基本的HTML文档。

使用cgi.rb

Ruby提供了一个名为cgi的特殊库,可以实现比上一个CGI脚本更复杂的交互。

让我们创建一个使用cgi的基本CGI脚本 -

#!/usr/bin/ruby

require "cgi"

cgi = CGI.new
puts cgi.header
puts "<html><body>This is a test</body></html>"

在这里,您创建了一个CGI对象,并使用它来为您打印标题行。

表格处理

使用类CGI可以通过两种方式访问HTML查询参数。假设我们给了一个URL /cgi-bin/test.cgi?FirstName = Zara&LastName = Ali。

您可以直接使用CGI#[] 访问参数FirstNameLastName,如下所示:

#!/usr/bin/ruby

require "cgi"
cgi = CGI.new
cgi["FirstName"] # =>  ["Zara"]
cgi["LastName"]  # =>  ["Ali"]

有另一种访问这些表单变量的方法。这个代码将给你一个哈希的所有键和值 -

#!/usr/bin/ruby

require "cgi"
cgi = CGI.new
h = cgi.params  # =>  {"FirstName"=>["Zara"],"LastName"=>["Ali"]}
h["FirstName"]  # =>  ["Zara"]
h["LastName"]   # =>  ["Ali"]

以下是检索所有密钥的代码 -

#!/usr/bin/ruby

require "cgi"
cgi = CGI.new
cgi.keys         # =>  ["FirstName", "LastName"]

如果表单包含多个具有相同名称的字段,则相应的值将作为数组返回到脚本。[]访问器只返回这些中的第一个。指定params方法的结果,以获取它们。

在这个例子中,假设表单有三个字段叫做“name”,我们输入三个名字“Zara”,“Huma”和“Nuha”

#!/usr/bin/ruby

require "cgi"
cgi = CGI.new
cgi["name"]        # => "Zara"
cgi.params["name"] # => ["Zara", "Huma", "Nuha"]
cgi.keys           # => ["name"]
cgi.params         # => {"name"=>["Zara", "Huma", "Nuha"]}

注意 - Ruby将自动处理GET和POST方法。这两种不同的方法没有单独的处理方法。

可以发送正确数据的关联但基本的表单将具有如下所示的HTML代码:

<html>
   <body>
      <form method = "POST" action = "http://www.example.com/test.cgi">
         First Name :<input type = "text" name = "FirstName" value = "" />
         <br />
         Last Name :<input type = "text" name = "LastName" value = "" /> 
         <input type = "submit" value = "Submit Data" />
      </form>
   </body>
</html>

创建表单和HTML

CGI包含大量用于创建HTML的方法。每个标签可以找到一种方法。为了启用这些方法,您必须通过调用CGI.new创建一个CGI对象。

为了使标签嵌套更容易,这些方法将其内容作为代码块。代码块应该返回一个String,它将被用作标签的内容。例如 -

#!/usr/bin/ruby

require "cgi"
cgi = CGI.new("html4")
cgi.out{
   cgi.html{
      cgi.head{ "
"+cgi.title{"This Is a Test"} } +
      cgi.body{ "
"+
         cgi.form{"
"+
            cgi.hr +
            cgi.h1 { "A Form: " } + "
"+
            cgi.textarea("get_text") +"
"+
            cgi.br +
            cgi.submit
         }
      }
   }
}

注意 - CGI类表单方法可以接受一个方法参数,它将设置在表单提交中使用的HTTP方法(GET,POST等等)。在此示例中使用的默认值为POST。

输出结果如下 -

Content-Type: text/html
Content-Length: 302

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Final//EN">

<HTML>
   <HEAD>
      <TITLE>This Is a Test</TITLE>
   </HEAD>
   <BODY>
      <FORM METHOD = "post" ENCTYPE = "application/x-www-form-urlencoded">
         <HR>
         <H1>A Form: </H1>
         <TEXTAREA COLS = "70" NAME = "get_text" ROWS = "10"></TEXTAREA>
         <BR>
         <INPUT TYPE = "submit">
      </FORM>
   </BODY>
</HTML>

引用字符string

处理URL和HTML代码时,必须小心引用某些字符。例如,斜杠字符(/)在URL中具有特殊含义,因此如果它不是路径名的一部分,则必须进行转义

例如,URL中的任何/在查询部分将被转换为字符string%2F,并且必须翻译成/使用它。空间和符号也是特殊字符。为了处理这个问题,CGI提供了例程CGI.escapeCGI.unescape

#!/usr/bin/ruby

require "cgi"
puts CGI.escape(Zara Ali/A Sweet & Sour Girl")

输出结果如下 -

Zara+Ali%2FA Sweet+%26+Sour+Girl")

#!/usr/bin/ruby

require "cgi"
puts CGI.escapeHTML("<h1>Zara Ali/A Sweet & Sour Girl</h1>")

输出结果如下 -

&lt;h1&gt;Zara Ali/A Sweet & Sour Girl&lt;/h1&gt;"

CGI课程有用的方法

以下是与CGI类相关的方法列表 -

cookie和会话

我们已经在不同的部分解释了这两个概念。请按照这些部分 -

网络托管服务器

您可以在互联网上查看以下主题,在基于Unix的服务器上托管您的网站 -

使用Ruby - SMTP发送电子邮件

简单邮件传输协议(SMTP)是一种协议,用于在邮件服务器之间发送电子邮件和路由电子邮件。

Ruby为简单邮件传输协议(SMTP)客户端连接提供了Net :: SMTP类,并提供了两种类方法开始

SMTP对象具有称为sendmail的实例方法,通常用于执行邮件邮件的工作。它需要三个参数 -

这是使用Ruby脚本发送一封电子邮件的简单方法。尝试一次 -

require "net/smtp"

message = <<MESSAGE_END
From: Private Person <me@fromdomain.com>
To: A Test User <test@todomain.com>
Subject: SMTP e-mail test

This is a test e-mail message.
MESSAGE_END

Net::SMTP.start("localhost") do |smtp|
  smtp.send_message message, "me@fromdomain.com", "test@todomain.com"
end

在这里,您已经在邮件中放置了基本的电子邮件,使用文档,请注意正确格式化标题。电子邮件需要一个FromToSubject标题,与电子邮件正文分开,空行。

要发送邮件,您使用Net :: SMTP连接到本地计算机上的SMTP服务器,然后使用send_message方法以及消息,从地址和目标地址作为参数(即使来自和地址是在电子邮件本身内,这些并不总是用于路由邮件)。

如果您的计算机上没有运行SMTP服务器,则可以使用Net :: SMTP与远程SMTP服务器进行通信。除非您使用Webmail服务(如Hotmail或Yahoo! Mail),否则您的电子邮件提供商将为您提供可以提供给Net :: SMTP的外发邮件服务器详细信息,如下所示:

Net::SMTP.start("mail.your-domain.com")

这行代码连接到mail.your-domain.com的端口25上的SMTP服务器,而不使用任何用户名或密码。但是,如果需要,可以指定端口号和其他详细信息。例如 -

Net::SMTP.start("mail.your-domain.com", 
                25, 
                "localhost", 
                "username", "password" :plain)

此示例使用纯文本格式的用户名和密码在mail.your-domain.com上连接到SMTP服务器。它将客户端的主机名标识为localhost。

使用Ruby发送HTML电子邮件

当您使用Ruby发送短信时,所有内容将被视为简单文本。即使您将文本消息中包含HTML标签,它将显示为简单文本,HTML标签将不会根据HTML语法进行格式化。但是,Ruby Net :: SMTP提供了将HTML消息作为HTML消息发送的选项。

发送电子邮件时,您可以指定一个Mime版本,内容类型和字符集来发送HTML电子邮件。

以邮件形式发送HTML内容的例子如下。尝试一次 -

require "net/smtp"

message = <<MESSAGE_END
From: Private Person <me@fromdomain.com>
To: A Test User <test@todomain.com>
MIME-Version: 1.0
Content-type: text/html
Subject: SMTP e-mail test

This is an e-mail message to be sent in HTML format

<b>This is HTML message.</b>
<h1>This is headline.</h1>
MESSAGE_END

Net::SMTP.start("localhost") do |smtp|
  smtp.send_message message, "me@fromdomain.com", "test@todomain.com"
end

发送附件作为电子邮件

要发送具有混合内容的电子邮件,需要将Content-type标题设置multipart / mixed然后可以在边界内指定文本和附件部分

一个边界以两个连字符开始,后跟一个唯一的号码,不能出现在邮件的邮件部分。表示电子邮件最终部分的最后一个边界也必须以两个连字符结尾。

使用pack(“m”)函数对附加文件进行编码,以便在传输之前具有base64编码。

以下是以附件形式发送/tmp/test.txt文件的示例。

require "net/smtp"

filename = "/tmp/test.txt"
# Read a file and encode it into base64 format
filecontent = File.read(filename)
encodedcontent = [filecontent].pack("m")   # base64

marker = "AUNIQUEMARKER"

body = <<EOF
This is a test email to send an attachement.
EOF

# Define the main headers.
part1 = <<EOF
From: Private Person <me@fromdomain.net>
To: A Test User <test@todmain.com>
Subject: Sending Attachement
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary = #{marker}
--#{marker}
EOF

# Define the message action
part2 = <<EOF
Content-Type: text/plain
Content-Transfer-Encoding:8bit

#{body}
--#{marker}
EOF

# Define the attachment section
part3 = <<EOF
Content-Type: multipart/mixed; name = "#{filename}"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename = "#{filename}"

#{encodedcontent}
--#{marker}--
EOF

mailtext = part1 + part2 + part3

# Let"s put our code in safe area
begin 
   Net::SMTP.start("localhost") do |smtp|
      smtp.sendmail(mailtext, "me@fromdomain.net", ["test@todmain.com"])
   end
rescue Exception => e  
   print "Exception occured: " + e  
end  

注意 - 您可以在数组中指定多个目的地,但应以逗号分隔。

Ruby - 套接字编程

Ruby提供两级访问网络服务。在低级别,您可以访问底层操作系统中的基本套接字支持,这允许您为面向连接和无连接协议实现客户端和服务器。

Ruby还具有提供对特定应用级网络协议(如FTP,HTTP等)的更高级别访问的库。

本章让您了解网络中最着名的概念 - 套接字编程。

什么是套接字?

套接字是双向通信通道的端点。套接字可以在一个进程内,在同一机器上的进程之间,或者在不同大陆的进程之间进行通信。

套接字可以通过多种不同的通道类型实现:Unix域套接字,TCP,UDP等。插座提供特定的类来处理常见的传输以及用于处理其余的通用接口。

插座有自己的词汇 -

没有 期限和描述
1

将用作运输机制的协议族。这些值是常量,例如PF_INET,PF_UNIX,PF_X25等。

2 类型

两个端点之间的通信类型,通常用于面向连接的协议的SOCK_STREAM和用于无连接协议的SOCK_DGRAM。

3 协议

通常为零,这可以用于标识域和类型中的协议的变体。

4 主机名

网络接口的标识符 -

一个字符string,可以是一个主机名,一个点四分之一地址,或一个冒号中的IPV6地址(可能是点)符号

一个字符string“<广播>”,它指定一个INADDR_BROADCAST地址。

一个零长度的字符string,指定INADDR_ANY,或

整数,以主机字节顺序解释为二进制地址。

5 港口

每个服务器监听呼叫一个或多个端口的客户端。端口可能是Fixnum端口号,包含端口号的字符string或服务名称。

一个简单的客户端

这里我们将编写一个非常简单的客户端程序,它将打开一个给定端口和给定主机的连接。Ruby类的TCPSocket提供打开这样一个socket的开放功能。

TCPSocket.open(hosname,端口)打开一个TCP连接到主机上的端口

一旦您打开了一个套接字,就可以像任何IO对象一样读取它。完成后,请记住关闭它,就像关闭文件一样。

以下代码是一个非常简单的客户端,连接到给定的主机和端口,从套接字读取任何可用的数据,然后退出 -

require "socket"      # Sockets are in standard library

hostname = "localhost"
port = 2000

s = TCPSocket.open(hostname, port)

while line = s.gets   # Read lines from the socket
   puts line.chop      # And print with platform line terminator
end
s.close               # Close the socket when done

一个简单的服务器

要编写Internet服务器,我们使用TCPServer类。TCPServer对象是TCPSocket对象的工厂。

现在调用TCPServer.open(hostname,port函数)为您的服务指定一个端口并创建一个TCPServer对象。

接下来,调用返回的TCPServer对象accept方法。此方法等待直到客户端连接到您指定的端口,然后返回表示到该客户端的连接的TCPSocket对象。

require "socket"               # Get sockets from stdlib

server = TCPServer.open(2000)  # Socket to listen on port 2000
loop {                         # Servers run forever
   client = server.accept       # Wait for a client to connect
   client.puts(Time.now.ctime)  # Send the time to the client
   client.puts "Closing the connection. Bye!"
   client.close                 # Disconnect from the client
}

现在,在后台运行这个服务器,然后运行上面的客户端来查看结果。

多客户端TCP服务器

互联网上的大多数服务器都是随时处理大量客户端的。

Ruby的Thread类可以轻松创建一个接受请求的多线程服务器,并立即创建一个新的执行线程来处理连接,同时允许主程序等待更多的连接 -

require "socket"                # Get sockets from stdlib

server = TCPServer.open(2000)   # Socket to listen on port 2000
loop {                          # Servers run forever
   Thread.start(server.accept) do |client|
   client.puts(Time.now.ctime) # Send the time to the client
   client.puts "Closing the connection. Bye!"
   client.close                # Disconnect from the client
   end
}

在此示例中,您有一个永久循环,当server.accept响应时,将创建一个新线程并立即启动,以使用传入线程的连接对象立即处理刚被接受的连接。然而,主程序立即循环并等待新的连接。

以这种方式使用Ruby线程意味着代码是可移植的,并且将以相同的方式在Linux,OS X和Windows上运行。

一个微小的网页浏览器

我们可以使用套接字库实现任何Internet协议。这里,例如,是用于获取网页内容的代码 -

require "socket"
 
host = "www.tutorialspoint.com"     # The web server
port = 80                           # Default HTTP port
path = "/index.htm"                 # The file we want 

# This is the HTTP request we send to fetch a file
request = "GET #{path} HTTP/1.0

"

socket = TCPSocket.open(host,port)  # Connect to server
socket.print(request)               # Send request
response = socket.read              # Read complete response
# Split response at first blank line into headers and body
headers,body = response.split("

", 2) 
print body                          # And display it

要实现类似的Web客户端,您可以使用预创建的库,如Net :: HTTP来处理HTTP。以下代码与前面的代码相当 -

require "net/http"                  # The library we need
host = "www.tutorialspoint.com"     # The web server
path = "/index.htm"                 # The file we want 

http = Net::HTTP.new(host)          # Create a connection
headers, body = http.get(path)      # Request the file
if headers.code == "200"            # Check the status code   
   print body                        
else                                
   puts "#{headers.code} #{headers.message}" 
end

请检查类似的库以使用FTP,SMTP,POP和IMAP协议。

进一步阅读

我们已经给你一个快速启动套接字编程。这是一个很大的主题,所以建议您通过Ruby Socket Library和Class Methods来查找更多详细信息。

Ruby - XML,XSLT和XPath教程

什么是XML?

可扩展标记语言(XML)是一种非常像HTML或SGML的标记语言。这是由万维网联盟推荐并作为开放标准提供的。

XML是一种便携式的开源语言,允许程序员开发可由其他应用程序读取的应用程序,无论操作系统和/或开发语言如何。

XML对于跟踪小到中等数量的数据非常有用,而不需要基于SQL的主干。

XML解析器体系结构和API

XML解析器有两种不同的风格:

当处理大文件时,SAX显然无法像DOM那样快速处理信息。另一方面,使用DOM专门可以真正地杀死你的资源,特别是如果用在很多小文件上。

SAX是只读的,而DOM允许更改XML文件。由于这两个不同的API互相补充,所以没有理由不能将它们用于大型项目。

使用Ruby解析和创建XML

操作XML的最常见方法是使用Sean Russell的REXML库。自2002年以来,REXML已经成为标准Ruby发行版的一部分。

REXML是符合XML 1.0标准的纯Ruby XML处理器。它是一个非验证的处理器,通过了所有的OASIS非验证一致性测试。

REXML解析器比其他可用的解析器具有以下优点 -

对于我们所有的XML代码示例,让我们使用一个简单的XML文件作为输入 -

<collection shelf = "New Arrivals">
   <movie title = "Enemy Behind">
      <type>War, Thriller</type>
      <format>DVD</format>
      <year>2003</year>
      <rating>PG</rating>
      <stars>10</stars>
      <description>Talk about a US-Japan war</description>
   </movie>
   <movie title = "Transformers">
      <type>Anime, Science Fiction</type>
      <format>DVD</format>
      <year>1989</year>
      <rating>R</rating>
      <stars>8</stars>
      <description>A schientific fiction</description>
   </movie>
   <movie title = "Trigun">
      <type>Anime, Action</type>
      <format>DVD</format>
      <episodes>4</episodes>
      <rating>PG</rating>
      <stars>10</stars>
      <description>Vash the Stampede!</description>
   </movie>
   <movie title = "Ishtar">
      <type>Comedy</type>
      <format>VHS</format>
      <rating>PG</rating>
      <stars>2</stars>
      <description>Viewable boredom</description>
   </movie>
</collection>

DOM类分析

我们首先用解析我们的XML数据我们首先要求rexml /文档库; 通常,为了方便起见,我们会将REXML包含进顶级命名空间中。

#!/usr/bin/ruby -w

require "rexml/document"
include REXML

xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)

# Now get the root element
root = xmldoc.root
puts "Root element : " + root.attributes["shelf"]

# This will output all the movie titles.
xmldoc.elements.each("collection/movie"){ 
   |e| puts "Movie Title : " + e.attributes["title"] 
}

# This will output all the movie types.
xmldoc.elements.each("collection/movie/type") {
   |e| puts "Movie Type : " + e.text 
}

# This will output all the movie description.
xmldoc.elements.each("collection/movie/description") {
   |e| puts "Movie Description : " + e.text 
}

输出结果如下 -

Root element : New Arrivals
Movie Title : Enemy Behind
Movie Title : Transformers
Movie Title : Trigun
Movie Title : Ishtar
Movie Type : War, Thriller
Movie Type : Anime, Science Fiction
Movie Type : Anime, Action
Movie Type : Comedy
Movie Description : Talk about a US-Japan war
Movie Description : A schientific fiction
Movie Description : Vash the Stampede!
Movie Description : Viewable boredom

SAX样分析

要处理相同的数据,movies.xml,以流为导向的方式,我们将定义一个侦听器类,其方法将是解析器回调目标

注意 - 不建议对一个小文件使用类似SAX的解析,这只是一个演示示例。

#!/usr/bin/ruby -w

require "rexml/document"
require "rexml/streamlistener"
include REXML


class MyListener
   include REXML::StreamListener
   def tag_start(*args)
      puts "tag_start: #{args.map {|x| x.inspect}.join(", ")}"
   end

   def text(data)
      return if data =~ /^w*$/     # whitespace only
      abbrev = data[0..40] + (data.length > 40 ? "..." : "")
      puts "  text   :   #{abbrev.inspect}"
   end
end

list = MyListener.new
xmlfile = File.new("movies.xml")
Document.parse_stream(xmlfile, list)

输出结果如下 -

tag_start: "collection", {"shelf"=>"New Arrivals"}
tag_start: "movie", {"title"=>"Enemy Behind"}
tag_start: "type", {}
   text   :   "War, Thriller"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
   text   :   "Talk about a US-Japan war"
tag_start: "movie", {"title"=>"Transformers"}
tag_start: "type", {}
   text   :   "Anime, Science Fiction"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
   text   :   "A schientific fiction"
tag_start: "movie", {"title"=>"Trigun"}
tag_start: "type", {}
   text   :   "Anime, Action"
tag_start: "format", {}
tag_start: "episodes", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
   text   :   "Vash the Stampede!"
tag_start: "movie", {"title"=>"Ishtar"}
tag_start: "type", {}
tag_start: "format", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
   text   :   "Viewable boredom"

XPath和Ruby

查看XML的另一种方法是XPath。这是一种描述如何在XML文档中定位特定元素和属性的伪语言,将该文档视为逻辑有序树。

REXML通过XPath支持XPath它假定了基于树的解析(文档对象模型),如上所述。

#!/usr/bin/ruby -w

require "rexml/document"
include REXML

xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)

# Info for the first movie found
movie = XPath.first(xmldoc, "//movie")
p movie

# Print out all the movie types
XPath.each(xmldoc, "//type") { |e| puts e.text }

# Get an array of all of the movie formats.
names = XPath.match(xmldoc, "//format").map {|x| x.text }
p names

输出结果如下 -

<movie title = "Enemy Behind"> ... </>
War, Thriller
Anime, Science Fiction
Anime, Action
Comedy
["DVD", "DVD", "DVD", "VHS"]

XSLT和Ruby

Ruby可以使用两种XSLT解析器。这里给出了每个的简要说明。

Ruby-Sablotron

该解析器由高桥正义写的和维护。这主要用于Linux操作系统,需要以下库 -

你可以在Ruby-Sablotron找到这个模块

XSLT4R

XSLT4R由Michael Neumann编写,可以在XML部分的RAA中找到。XSLT4R使用简单的命令行界面,尽管它可以替代地在第三方应用程序中使用来转换XML文档。

XSLT4R需要XMLScan进行操作,这包括在XSLT4R存档中,也是一个100%的Ruby模块。这些模块可以使用标准的Ruby安装方法安装(即ruby install.rb)。

XSLT4R具有以下语法 -

ruby xslt.rb stylesheet.xsl document.xml [arguments]

如果要在应用程序中使用XSLT4R,可以包括XSLT并输入所需的参数。这是例子 -

require "xslt"

stylesheet = File.readlines("stylesheet.xsl").to_s
xml_doc = File.readlines("document.xml").to_s
arguments = { "image_dir" => "/...." }

sheet = XSLT::Stylesheet.new( stylesheet, arguments )

# output to StdOut
sheet.apply( xml_doc )

# output to "str"
str = ""
sheet.output = [ str ]
sheet.apply( xml_doc )

进一步阅读

使用Ruby - SOAP4R的Web服务

什么是SOAP?

简单对象访问协议(SOAP)是一种跨平台和语言无关的基于XML的RPC协议,通常(但不一定)HTTP。

它使用XML对远程过程调用的信息进行编码,并将HTTP通过网络从客户端传输到服务器,反之亦然。

SOAP比其他技术(如COM,CORBA等)具有以下优点:例如,其相对便宜的部署和调试成本,其可扩展性和易用性以及针对不同语言和平台的多种实现方式的存在。

请参阅我们的简单教程SOAP来详细了解它。

本章使您熟悉Ruby(SOAP4R)的SOAP实现。这是一个基本的教程,所以如果你需要一个深刻的细节,你需要引用其他资源。

安装SOAP4R

SOAP4R是由Hiroshi Nakamura开发的Ruby的SOAP实现,可以从 -

注意 - 可能很有可能您已经安装了此组件。

Download SOAP

如果您知道gem实用程序,则可以使用以下命令安装SOAP4R和相关软件包。

$ gem install soap4r --include-dependencies

如果您在Windows上工作,则需要从上述位置下载压缩文件,并且需要使用标准安装方法通过运行ruby install.rb进行安装

编写SOAP4R服务器

SOAP4R支持两种不同类型的服务器 -

本章详细介绍了独立服务器的编写。编写SOAP服务器时涉及以下步骤。

步骤1 - 继承SOAP :: RPC :: StandaloneServer类

要实现自己的独立服务器,您需要编写一个新类,这将是SOAP :: StandaloneServer的子代,如下所示:

class MyServer < SOAP::RPC::StandaloneServer
  ...............
end

注意 - 如果要编写基于FastCGI的服务器,则需要将SOAP :: RPC :: CGIStub作为父类,其余的过程将保持不变。

步骤2 - 定义处理方法

第二步是编写您想要向外界公开的Web服务方法。

它们可以写成简单的Ruby方法。例如,我们来写两个方法来添加两个数字并划分两个数字 -

class MyServer < SOAP::RPC::StandaloneServer
   ...............

   # Handler methods
   def add(a, b)
      return a + b
   end
   def div(a, b) 
      return a / b 
   end
end

步骤3 - 公布处理方法

下一步是将我们定义的方法添加到我们的服务器。所述初始化方法用于暴露服务的方法与以下两种方法之一-

class MyServer < SOAP::RPC::StandaloneServer
   def initialize(*args)
      add_method(receiver, methodName, *paramArg)
   end
end

这是参数的描述 -

没有 参数说明
1 接收器

包含methodName方法的对象。您将定义与methodDef方法在同一类中的服务方法,此参数为self

2 methodName

由于RPC请求而调用的方法的名称。

3 参数

指定参数名称和参数模式。

要了解inoutout参数的用法,请考虑以下服务方法,它使用两个参数(inParam和inoutParam),返回一个正常的返回值(retVal)和另外两个参数:inoutParamoutParam -

def aMeth(inParam, inoutParam)
   retVal = inParam + inoutParam
   outParam = inParam . inoutParam
   inoutParam = inParam * inoutParam
   return retVal, inoutParam, outParam
end

现在我们可以公开这种方法如下 -

add_method(self, "aMeth", [
   %w(in inParam),
   %w(inout inoutParam),
   %w(out outParam),
   %w(retval return)
])

步骤4 - 启动服务器

最后一步是通过实例化派生类的一个实例并调用start方法来启动服务器

myServer = MyServer.new("ServerName", "urn:ruby:ServiceName", hostname, port)

myServer.start

以下是所需参数的说明 -

没有 参数说明
1 服务器名称

一个服务器名称,你可以给你最喜欢的。

2 urn:ruby:ServiceName

这里urn:ruby是常量,但是您可以为此服务器提供唯一的ServiceName名称。

3 主机名

指定此服务器将侦听的主机名。

4 港口

用于Web服务的可用端口号。

现在,使用上述步骤,让我们写一个独立的服务器 -

require "soap/rpc/standaloneserver"

begin
   class MyServer < SOAP::RPC::StandaloneServer

      # Expose our services
      def initialize(*args)
         add_method(self, "add", "a", "b")
         add_method(self, "div", "a", "b")
      end

      # Handler methods
      def add(a, b)
         return a + b
      end
      def div(a, b) 
         return a / b 
      end
end
   server = MyServer.new("MyServer", 
            "urn:ruby:calculation", "localhost", 8080)
   trap("INT){
      server.shutdown
   }
   server.start
rescue => err
   puts err.message
end

执行时,该服务器应用程序启动上一个独立的SOAP服务器本地主机并侦听请求的端口 8080。它暴露了一个服务方法,添加DIV,它有两个参数,并返回结果。

现在,您可以在后台运行此服务器,如下所示:

$ ruby MyServer.rb&

编写SOAP4R客户端

SOAP RPC :: ::驱动程序类为编写SOAP客户端应用程序的支持。本章介绍了这个类,并在应用的基础上演示了它的用法。

以下是您需要调用SOAP服务的最低限度信息 -

现在,我们将编写一个SOAP客户端,它将调用上面例子中定义的名为adddiv的服务方法

以下是创建SOAP客户端的主要步骤。

步骤1 - 创建SOAP驱动程序实例

我们通过调用其新方法创建一个SOAP :: RPC :: Driver的实例,如下所示:

SOAP::RPC::Driver.new(endPoint, nameSpace, soapAction)

以下是所需参数的说明 -

没有 参数说明
1 endPoint

要连接的SOAP服务器的URL。

2 nameSpace

用于使用此SOAP :: RPC :: Driver对象的所有RPC的命名空间。

3 soapAction

HTTP标头的SOAPAction字段的值。如果nil默认为空字符string“”。

步骤2 - 添加服务方法

要将SOAP服务方法添加到SOAP :: RPC :: Driver中,我们可以使用SOAP :: RPC :: Driver实例调用以下方法

driver.add_method(name, *paramArg)

这是参数的描述 -

没有 参数说明
1 name

远程Web服务方法的名称。

2 参数

指定远程过程参数的名称。

步骤3 - 调用SOAP服务

最后一步是使用SOAP :: RPC :: Driver实例发送SOAP服务,如下所示:

result = driver.serviceMethod(paramArg...)

这里serviceMethod是实际的Web服务方法,paramArg ...是传递服务方法所需的列表参数。

基于上述步骤,我们将编写一个SOAP客户端,如下所示:

#!/usr/bin/ruby -w

require "soap/rpc/driver"

NAMESPACE = "urn:ruby:calculation"
URL = "http://localhost:8080/"

begin
   driver = SOAP::RPC::Driver.new(URL, NAMESPACE)
   
   # Add remote sevice methods
   driver.add_method("add", "a", "b")

   # Call remote service methods
   puts driver.add(20, 30)
rescue => err
   puts err.message
end

进一步阅读

我已经用Ruby解释了Web服务的基本概念。如果您想进一步深入了解,那么有以下链接可以使用Ruby查找有关Web服务的更多详细信息

Ruby - Tk指南

Ruby的标准图形用户界面(GUI)是Tk。Tk开始是由John Ousterhout开发的Tcl脚本语言的GUI。

Tk具有独特的区别,成为唯一的跨平台GUI。Tk在Windows,Mac和Linux上运行,并在每个操作系统上提供了原生的外观。

基于Tk的应用程序的基本组件称为小部件。组件有时也称为窗口,因为在Tk中,“窗口”和“窗口小部件”通常可互换使用。

Tk应用程序遵循一个小部件层次结构,其中任何数量的小部件可以放置在另一个小部件中,而另一个小部件中的这些小部件则无限制。Tk程序中的主窗口小部件称为根小部件,可以通过创建TkRoot类的新实例来创建。

安装

Ruby Tk绑定是用Ruby分发的,但是Tk是一个单独的安装。Windows用户可以从ActiveState的ActiveTcl下载单击Tk 安装

Mac和Linux用户可能不需要安装它,因为它已经与操作系统一起安装了很多机会,但如果没有安装,则可以下载预创建的软件包或从Tcl Developer Xchange获取源代码

简单Tk应用程序

Ruby / Tk程序的典型结构是创建主窗口窗口(TkRoot的一个实例),向其添加小部件以创建用户界面,然后通过调用Tk.mainloop启动主事件循环

传统的Hello World!Ruby / Tk的例子看起来像这样 -

require "tk"

root = TkRoot.new { title "Hello, World!" }
TkLabel.new(root) do
   text "Hello, World!"
   pack { padx 15 ; pady 15; side "left" }
end
Tk.mainloop

这里,加载tk扩展模块后,我们使用TkRoot.new创建一个根级别的框架然后,我们将一个TkLabel小部件作为根框架的小孩,为标签设置几个选项。最后,我们打包根框架并进入主GUI事件循环。

如果你运行这个脚本,它输出结果如下-

Ruby / Tk Hello World

Ruby / Tk小部件类

有各种Ruby / Tk类的列表,可用于使用Ruby / Tk创建所需的GUI。

标准配置选项

所有窗口小部件都有许多不同的配置选项,通常可以控制它们的显示方式以及它们的行为。当然可用的选项取决于小部件类。

以下是所有标准配置选项的列表,可用于任何Ruby / Tk小部件。

Ruby / Tk几何管理

几何管理根据要求处理不同的小部件。Tk中的几何管理依赖于主和从属小部件的概念。

主人是一个小部件,通常是一个顶级窗口或一个框架,它将包含其他小部件,这些小部件被称为从属。您可以将几何管理器视为控制主窗口小部件,并决定将显示哪些内容。

几何管理器将要求每个从属窗口小部件的自然尺寸,或者最理想地显示多大。然后,当它要求几何管理器管理特定的从属窗口小部件时,它将该信息与程序提供的任何参数相结合。

有三个几何管理员放置,网格,负责控制界面中每个窗口小部件的大小和位置。

Ruby / Tk事件处理

Ruby / Tk支持事件循环,它从操作系统接收事件。这些是按钮按下,按键,鼠标移动,窗口调整大小等等。

Ruby / Tk负责为您管理此事件循环。它会确定事件适用的窗口小部件(用户是否点击此按钮?如果按下一个键,哪个文本框有焦点?),并相应地进行调度。各个小部件知道如何响应事件,例如,当鼠标移动时,按钮可能会更改颜色,并在鼠标离开时还原。

在更高层次上,Ruby / Tk在您的程序中调用回调,以表明widget的重要性。对于任一情况,您都可以提供代码块或Ruby Proc对象,该对象指定应用程序如何响应事件或回调。

我们来看看如何使用bind方法将基本窗口系统事件与处理它们的Ruby过程相关联。绑定的最简单形式作为其输入,指示事件名称的字符string和Tk用于处理事件的代码块。

例如,要抓住ButtonRelease事件在某个小部件上的第一个鼠标按钮,你会写 -

someWidget.bind("ButtonRelease-1") {
   ....code block to handle this event...
}

事件名称可以包括其他修饰符和细节。修饰符是一个像ShiftControlAlt这样的字符string,表示其中一个修饰键被按下。

所以,例如,抓住当用户按住Ctrl键并单击鼠标右键时生成的事件

someWidget.bind("Control-ButtonPress-3", proc { puts "Ouch!" })

很多的Ruby / Tk部件可以触发回调当用户激活它们,你可以使用命令回调到指定是发生在某代码块或程序被调用。如前所述,您可以在创建窗口小部件时指定命令回调过程 -

helpButton = TkButton.new(buttonFrame) {
   text "Help"
   command proc { showHelp }
}

或者您可以稍后使用小部件的命令方法进行分配-

helpButton.command proc { showHelp }

由于命令方法接受过程或代码块,您还可以将以前的代码示例写为 -

helpButton = TkButton.new(buttonFrame) {
   text "Help"
   command { showHelp }
}

配置方法

配置方法可以用来设置和检索的任何小窗口配置的值。例如,要更改按钮的宽度,您可以随时调用configure方法,如下所示:

require "tk"

button = TkButton.new {
   text "Hello World!"
   pack
}
button.configure("activebackground", "blue")
Tk.mainloop

要获取当前窗口小部件的值,只需提供如下的值即可:

color = button.configure("activebackground")

您也可以调用configure,而不需要任何选项,这将为您提供所有选项及其值的列表。

cget方法

为了简单地检索选项的值,configure将返回比您通常想要的更多信息。cget方法只返回当前值。

color = button.cget("activebackground")

Ruby - LDAP教程

Ruby / LDAP是Ruby的扩展库。它提供了一些LDAP库的接口,如OpenLDAP,UMich LDAP,Netscape SDK,ActiveDirectory。

用于应用程序开发的通用API在RFC1823中描述,并由Ruby / LDAP支持。

Ruby / LDAP安装

您可以从SOURCEFORGE.NET下载并安装完整的Ruby / LDAP软件包

在安装Ruby / LDAP之前,请确保您具有以下组件 -

现在,您可以使用标准的Ruby安装方法。在开始之前,如果您想查看extconf.rb的可用选项,请使用“--help”选项运行它。

$ ruby extconf.rb [--with-openldap1|--with-openldap2| 
                   --with-netscape|--with-wldap32]
$ make
$ make install

- 如果您在Windows上创建软件,则可能需要使用nmake而不是make

建立LDAP连接

这是一个两步的过程 -

步骤1 - 创建连接对象

以下是创建到LDAP目录的连接的语法。

LDAP::Conn.new(host = "localhost", port = LDAP_PORT)

该调用返回一个新的LDAP ::康恩连接到服务器,主机,端口的端口

步骤2 - 绑定

这是我们通常指定用于会话剩余部分的用户名和密码的地方。

以下是绑定LDAP连接的语法,使用DN,dn,凭据,pwd和bind方法,方法 -

conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE)do
....
end

您可以使用相同的方法而不使用代码块。在这种情况下,您需要如下解释绑定连接:

conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE)
....
conn.unbind

如果给出了一个代码块,则自动被赋予块。

我们现在可以执行搜索,添加,修改或删除绑定方法(bind和unbind)之间的操作,只要我们有适当的权限。

假设我们正在本地服务器上工作,我们可以把它们放在一起,使用适当的主机,域,用户ID和密码等。

#/usr/bin/ruby -w

require "ldap"

$HOST =    "localhost"
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind("cn = root, dc = localhost, dc = localdomain","secret")
....
conn.unbind

添加LDAP条目

添加LDPA条目是一个两步过程 -

步骤1 - 创建LDAP :: Mod对象

我们需要LDAP :: Mod对象传递给conn.add方法来创建一个条目。以下是创建LDAP :: Mod对象的简单语法-

Mod.new(mod_type, attr, vals)

此调用返回LDAP :: Mod对象,可以传递给LDAP :: Conn类中的方法,如Conn#add,Conn#add_ext,Conn#modify和Conn#modify_ext。

第2步 - 调用conn.add方法

一旦我们准备好使用LDAP :: Mod对象,我们可以调用conn.add方法来创建一个条目。这是一个调用此方法的语法 -

conn.add(dn, attrs)

此方法添加一个包含DN,dn和属性attrs的条目这里,attrs应该是LDAP :: Mod对象的数组或属性/值数组对的哈希。

这是一个完整的例子,它将创建两个目录项 -

#/usr/bin/ruby -w

require "ldap"

$HOST =    "localhost"
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind("cn = root, dc = localhost, dc = localdomain","secret")

conn.perror("bind")
entry1 = [
   LDAP.mod(LDAP::LDAP_MOD_ADD,"objectclass",["top","domain"]),
   LDAP.mod(LDAP::LDAP_MOD_ADD,"o",["TTSKY.NET"]),
   LDAP.mod(LDAP::LDAP_MOD_ADD,"dc",["localhost"]),
]

entry2 = [
   LDAP.mod(LDAP::LDAP_MOD_ADD,"objectclass",["top","person"]),
   LDAP.mod(LDAP::LDAP_MOD_ADD, "cn", ["Zara Ali"]),
   LDAP.mod(LDAP::LDAP_MOD_ADD | LDAP::LDAP_MOD_BVALUES, "sn", 
                     ["ttate","ALI", "zero00zero"]),
]

begin
   conn.add("dc = localhost, dc = localdomain", entry1)
   conn.add("cn = Zara Ali, dc = localhost, dc =  localdomain", entry2)
rescue LDAP::ResultError
   conn.perror("add")
   exit
end
conn.perror("add")
conn.unbind

修改LDAP条目

修改条目与添加条目类似。只需调用modify方法,而不是添加要修改的属性。这是一个简单的修改方法语法

conn.modify(dn, mods)

此方法修改具有DN,dn属性mod的条目这里,mods应该是LDAP :: Mod对象的数组或属性/值数组对的散列。

要修改我们在上一节中添加的条目的姓氏,我们将写 -

#/usr/bin/ruby -w

require "ldap"

$HOST =    "localhost"
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind("cn = root, dc = localhost, dc = localdomain","secret")

conn.perror("bind")
entry1 = [
   LDAP.mod(LDAP::LDAP_MOD_REPLACE, "sn", ["Mohtashim"]),
]

begin
   conn.modify("cn = Zara Ali, dc = localhost, dc = localdomain", entry1)
rescue LDAP::ResultError
   conn.perror("modify")
   exit
end
conn.perror("modify")
conn.unbind

删除LDAP条目

要删除一个条目,请调用具有可分辨名称delete方法作为参数。这是一个简单的delete方法的语法

conn.delete(dn)

此方法将删除具有DN,dn的条目

要删除我们在上一节中添加的Zara Mohtashim条目,我们将写 -

#/usr/bin/ruby -w

require "ldap"

$HOST =    "localhost"
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind("cn = root, dc = localhost, dc = localdomain","secret")

conn.perror("bind")
begin
   conn.delete("cn = Zara-Mohtashim, dc = localhost, dc = localdomain")
rescue LDAP::ResultError
   conn.perror("delete")
   exit
end
conn.perror("delete")
conn.unbind

修改可分辨名称

使用modify方法修改条目的可分辨名称是不可能的而是使用modrdn方法。这里是modrdn方法的简单语法-

conn.modrdn(dn, new_rdn, delete_old_rdn)

该方法使用DN,dn修改条目的RDN ,给出新的RDN,new_rdn如果delete_old_rdntrue,则旧的RDN值将从条目中删除。

假设我们有以下条目 -

dn: cn = Zara Ali,dc = localhost,dc = localdomain
cn: Zara Ali
sn: Ali
objectclass: person

然后,我们可以使用以下代码修改其可分辨名称 -

#/usr/bin/ruby -w

require "ldap"

$HOST =    "localhost"
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind("cn = root, dc = localhost, dc = localdomain","secret")

conn.perror("bind")
begin
   conn.modrdn("cn = Zara Ali, dc = localhost, dc = localdomain", "cn = Zara Mohtashim", true)
rescue LDAP::ResultError
   conn.perror("modrdn")
   exit
end
conn.perror("modrdn")
conn.unbind

执行搜索

要在LDAP目录上执行搜索,请使用搜索方法与三种不同的搜索模式之一 -

在这里,我们将搜索整个子树的入口dc = localhost,dc = localdomain个人对象 -

#/usr/bin/ruby -w

require "ldap"

$HOST =    "localhost"
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

base = "dc = localhost,dc = localdomain"
scope = LDAP::LDAP_SCOPE_SUBTREE
filter = "(objectclass = person)"
attrs = ["sn", "cn"]

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind("cn = root, dc = localhost, dc = localdomain","secret")

conn.perror("bind")
begin
   conn.search(base, scope, filter, attrs) { |entry|
      # print distinguished name
      p entry.dn
      # print all attribute names
      p entry.attrs
      # print values of attribute "sn"
      p entry.vals("sn")
      # print entry as Hash
      p entry.to_hash
   }
rescue LDAP::ResultError
   conn.perror("search")
   exit
end
conn.perror("search")
conn.unbind

这将为每个匹配的条目调用给定的代码块,其中LDAP条目由LDAP :: Entry类的实例表示。使用搜索的最后一个参数,您可以指定感兴趣的属性,省略所有其他属性。如果您在此处传递零,则所有属性将返回与关系数据库中的“SELECT *”相同。

LDAP :: Entry类的dn方法(get_dn的别名)返回条目的可分辨名称,使用to_hash方法可以获取其属性(包括可分辨名称)的哈希表示。要获取条目属性的列表,请使用attrs方法(get_attributes的别名)。另外,要获取一个特定属性值的列表,请使用vals方法(get_values的别名)。

处理错误

Ruby / LDAP定义了两个不同的异常类 -

进一步阅读

有关LDAP方法的完整详细信息,请参阅LDAP文档的标准文档

Ruby - 多线程

传统程序具有单个执行线程:构成程序的语句或指令将依次执行,直到程序终止。

多线程程序有多个执行线程。在每个线程中,语句按顺序执行,但线程本身可以在多核CPU上并行执行。通常在单个CPU机器上,并行实际并行执行多个线程,但是通过交织线程的执行来模拟并行性。

Ruby使用Thread轻松编写多线程程序Ruby线程是一种在代码中实现并发性的轻量级和高效的方法。

创建Ruby线程

要启动新线程,只需将一个块与一个调用Thread.new相关联将创建一个新线程来执行该块中的代码,原始线程将立即Thread.new返回,并使用下一条语句继续执行 -

# Thread #1 is running here
Thread.new {
   # Thread #2 runs this code
}
# Thread #1 runs this code

这是一个例子,它显示了我们如何使用多线程的Ruby程序。

#!/usr/bin/ruby

def func1
   i = 0
   while i<=2
      puts "func1 at: #{Time.now}"
      sleep(2)
      i = i+1
   end
end

def func2
   j = 0
   while j<=2
      puts "func2 at: #{Time.now}"
      sleep(1)
      j = j+1
   end
end

puts "Started At #{Time.now}"
t1 = Thread.new{func1()}
t2 = Thread.new{func2()}
t1.join
t2.join
puts "End at #{Time.now}"

输出结果如下 -

Started At Wed May 14 08:21:54 -0700 2008
func1 at: Wed May 14 08:21:54 -0700 2008
func2 at: Wed May 14 08:21:54 -0700 2008
func2 at: Wed May 14 08:21:55 -0700 2008
func1 at: Wed May 14 08:21:56 -0700 2008
func2 at: Wed May 14 08:21:56 -0700 2008
func1 at: Wed May 14 08:21:58 -0700 2008
End at Wed May 14 08:22:00 -0700 2008

线程生命周期

Thread.new创建一个新的线程你也可以使用同义词Thread.startThread.fork

创建线程后无需启动线程,当CPU资源可用时,它将自动运行。

Thread类定义了一些在运行时查询和操作线程的方法。线程运行与调用Thread.new相关联的块中的代码,然后它停止运行。

该块中最后一个表达式的值是线程的值,可以通过调用Thread对象value方法获得如果线程已经运行到完成,那么值将立即返回线程的值。否则,方法将阻塞,直到线程完成才返回。

类方法Thread.current返回表示当前线程的Thread对象。这允许线程自己操纵。类方法Thread.main返回表示主线程的Thread对象。这是Ruby程序启动时开始执行的初始线程。

您可以通过调用该线程的Thread.join方法等待一个特定的线程来完成调用线程将阻塞,直到给定的线程完成。

线程和例外

如果在主线程中引发异常,并且不在任何地方处理,则Ruby解释器将打印一条消息并退出。在线程中,主线程除外,未处理的异常会导致线程停止运行。

如果一个线程牛逼退出,因为未处理的异常,而另一个线程小号呼叫t.join或t.value,则发生在异常牛逼在螺纹凸起小号

如果Thread.abort_on_exceptionfalse,默认情况下,一个未处理的异常会直接杀死当前线程,其余所有的线程继续运行。

如果您希望任何线程中的任何未处理的异常导致解释器退出,请将类方法Thread.abort_on_exception设置true

t = Thread.new { ... }
t.abort_on_exception = true

线程变量

当线程创建时,线程通常可以访问范围内的任何变量。线程块的局部变量是线程本地的,不会共享。

线程类具有一个特殊的功能,可以通过名称创建和访问线程局部变量。你只需要将线程对象看作是一个哈希,使用[] =写入元素,然后使用[]读取它们。

在这个例子中,每个线程使用关键mycount将一个变量count的当前值记录在一个threadlocal变量中

#!/usr/bin/ruby

count = 0
arr = []

10.times do |i|
   arr[i] = Thread.new {
      sleep(rand(0)/10.0)
      Thread.current["mycount"] = count
      count += 1
   }
end

arr.each {|t| t.join; print t["mycount"], ", " }
puts "count = #{count}"

这产生以下结果 -

8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10

主线程等待子线程完成,然后打印出每个线程捕获计数值

线程优先级

影响线程调度的第一个因素是线程优先级:高优先级线程在低优先级线程之前被调度。更准确地说,如果没有较高优先级的线程等待运行,线程将只获得CPU时间。

您可以设置并查询优先级为priority优先级的Ruby Thread对象的优先新创建的线程与创建它的线程的优先级相同。主线程从优先级0开始。

在开始运行之前,没有办法设置线程的优先级。然而,线程可以将其自身的优先级提高或降低为所需的第一个动作。

线程排除

如果两个线程共享对相同数据的访问,并且至少有一个线程修改该数据,那么您必须特别小心,以确保没有线程可以看到数据处于不一致的状态。这被称为线程排除

Mutex是一个实现一个简单信号量锁的类,用于互斥某些共享资源。也就是说,只有一个线程可以在给定时间保持锁定。其他线程可能会选择等待锁可用,或者可以简单地选择立即显示错误,指示锁不可用。

通过在互斥体的控制下对共享数据进行所有访问,我们确保一致性和原子操作。让我们来在线运行例子,第一个没有mutax,第二个与mutax -

没有Mutax的例子

#!/usr/bin/ruby
require "thread"

count1 = count2 = 0
difference = 0
counter = Thread.new do
   loop do
      count1 += 1
      count2 += 1
   end
end
spy = Thread.new do
   loop do
      difference += (count1 - count2).abs
   end
end
sleep 1
puts "count1 :  #{count1}"
puts "count2 :  #{count2}"
puts "difference : #{difference}"

输出结果如下 -

count1 :  1583766
count2 :  1583766
difference : 0
#!/usr/bin/ruby
require "thread"
mutex = Mutex.new

count1 = count2 = 0
difference = 0
counter = Thread.new do
   loop do
      mutex.synchronize do
         count1 += 1
         count2 += 1
      end
   end
end
spy = Thread.new do
   loop do
      mutex.synchronize do
         difference += (count1 - count2).abs
      end
   end
end
sleep 1
mutex.lock
puts "count1 :  #{count1}"
puts "count2 :  #{count2}"
puts "difference : #{difference}"

输出结果如下 -

count1 :  696591
count2 :  696591
difference : 0

处理死锁

当我们开始使用Mutex对象进行线程排除时,我们必须小心避免死锁死锁是当所有线程等待获取另一个线程持有的资源时发生的情况。因为所有线程都被阻塞,所以它们不能释放它们所持有的锁。并且因为它们不能释放锁,所以没有其他线程可以获得这些锁。

这就是条件变量的映射条件变量仅仅是一个与资源相关联,并且在特定的保护内使用的信号的互斥当您需要不可用的资源时,请等待条件变量。该操作释放相应互斥体上的锁定当一些其他线程发出资源可用时,原始线程脱离等待,同时重新获得关键区域的锁定。

#!/usr/bin/ruby
require "thread"
mutex = Mutex.new

cv = ConditionVariable.new
a = Thread.new {
   mutex.synchronize {
      puts "A: I have critical section, but will wait for cv"
      cv.wait(mutex)
      puts "A: I have critical section again! I rule!"
   }
}

puts "(Later, back at the ranch...)"

b = Thread.new {
   mutex.synchronize {
      puts "B: Now I am critical, but am done with cv"
      cv.signal
      puts "B: I am still critical, finishing up"
   }
}
a.join
b.join

输出结果如下 -

A: I have critical section, but will wait for cv
(Later, back at the ranch...)
B: Now I am critical, but am done with cv
B: I am still critical, finishing up
A: I have critical section again! I rule!

线程状态

有五个可能的返回值对应于五种可能的状态,如下表所示。状态方法返回线程的状态。

线程状态 返回值
可运行
睡眠 睡眠
中止 中止
正常终止 false
终止异常

线程类方法

以下方法由Thread提供,它们适用于程序中可用的所有线程。这些方法将被称为使用Thread类名,如下所示:

Thread.abort_on_exception = true

线程实例方法

这些方法适用于线程的实例。这些方法将被称为使用Thread的一个实例,如下所示:

#!/usr/bin/ruby

thr = Thread.new do   # Calling a class method new
   puts "In second thread"
   raise "Raise exception"
end
thr.join   # Calling an instance method join

Ruby - 内置函数

由于Object包含内核模块,所以Ruby程序中的任何地方都可以使用它的方法。它们可以在没有接收器(功能形式)的情况下被调用。因此,它们通常被称为功能。

数字功能

以下是与号码相关的内置函数的列表。它们应该如下使用 -

#!/usr/bin/ruby

num = 12.40
puts num.floor      # 12
puts num + 10       # 22.40
puts num.integer?   # false  as num is a float.

输出结果如下 -

12
22.4
false

float功能

数学函数

转换字段说明符

函数sprintf(fmt [,arg ...])和format(fmt [,arg ...])返回一个字符string,其中arg根据fmt进行格式化。格式化规范与C编程语言中的sprintf基本相同。在转换说明(%然后进行转换字段指定符)FMT被相应的参数的格式的字符string替换。

以下是使用示例 -

#!/usr/bin/ruby

str = sprintf("%s
", "abc")   # => "abc
" (simplest form)
puts str 

str = sprintf("d=%d", 42)      # => "d=42" (decimal output)
puts str 

str = sprintf("%04x", 255)     # => "00ff" (width 4, zero padded)
puts str 

str = sprintf("%8s", "hello")  # => " hello" (space padded)
puts str 

str = sprintf("%.2s", "hello") # => "he" (trimmed by precision)
puts str 

输出结果如下 -

abc
d=42
00ff
   hello
he

测试功能参数

功能测试(测试中,f1 [,F2])执行由字符指定了以下文件测试之一测试为了提高可读性,您应该使用File类方法(例如File ::可读?)而不是此函数。

以下是使用示例。假设main.rb存在读,写和不执行权限 -

#!/usr/bin/ruby

puts test(?r, "main.rb" )   # => true
puts test(?w, "main.rb" )   # => true
puts test(?x, "main.rb" )   # => false

输出结果如下 -

true
true
false

Ruby - 预定义变量

Ruby的预定义变量会影响整个程序的行为,因此不推荐在库中使用它们。

大多数预定义变量中的值可以通过替代方法访问。

下表列出了所有Ruby的预定义变量。

没有 变量名称和描述
1 $!

提出的最后一个异常对象。也可以在rescue子句中使用=>来访问异常对象

2 $ @

堆栈回溯募集的最后一个异常。堆栈回溯信息可以通过Exception#backtrace方法检索最后一个异常。

3 $ /

输入记录分隔符(默认为换行符)。获取,readline等,将他们的输入记录分隔符作为可选参数。

4 $

输出记录分隔符(默认为nil)。

5 $,

要打印的参数和Array#join之间的输出分隔符(默认为nil)。您可以将数组明确指定给Array#join。

6 $;

split的默认分隔符(默认为nil)。您可以为String#split指定明确的分隔符。

7 $。

从当前输入文件读取的最后一行的编号。相当于ARGF.lineno。

8 $ <

ARGF的同义词

9 $>

$ defout的同义词。

10 $ 0

正在执行的当前Ruby程序的名称。

11 $$

正在执行的当前Ruby程序的进程pid。

12 $?

最后一个进程的退出状态终止。

13 $:

$ LOAD_PATH的同义词。

14 $ DEBUG

如果指定了-d或--debug命令行选项,则为true。

15 $ defout

printprintf的目标输出默认为$ stdout)。

16 $ F

指定-a时接收分割输出的变量如果指定-a命令行选项以及-p或-n选项,则设置此变量。

17 $ FILENAME

目前正在从ARGF读取的文件的名称。相当于ARGF.filename。

18 $ LOAD_PATH

一个数组,用于加载和要求方法加载文件时要保存要搜索的目录。

19 $ SAFE

安全级别

0→不对外部提供(污染)数据执行检查。(默认)

1→禁止使用污染数据的潜在危险操作。

2→禁止对进程和文件进行潜在危险的操作。

3→所有新创建的对象都被认为是污染的。

4→禁止修改全局数据。

20 $ stdin

标准输入(默认为STDIN)。

21 $ stdout

标准输出(默认为STDOUT)。

22 $ stderr

标准错误(默认为STDERR)。

23 $ VERBOSE

如果指定了-v,-w或--verbose命令行选项,则为True。

24 $ - x

解释器选项-x(x = 0,a,d,F,i,K,l,p,v)的值。这些选项列在下面

25 $ -0

解释器选项-x的值和$ /的别名。

26 $ -a

解释器选项-x的值,如果选项-a被设置,则为true。只读。

27 $ -d

解释器选项-x的值和$ DEBUG的别名

28 $ -F

解释器选项-x和别名$ ;.

29 $ -i

解释器选项-x和in-place-edit模式的值保存扩展名,否则为nil。可以启用或禁用就地编辑模式。

30 $ -I

解释器选项-x的值和$:的别名。

31 $ -l

解释器选项-x的值,如果选项-lis设置为true。只读。

32 $ -p

解释器选项-x的值,如果选项-pis设置为true。只读。

33 $ _

局部变量,最后一个字符string通过gets或readline在当前作用域中读取。

34 $

与最后一场比赛相关的局部变量MatchDataRegex#match方法返回最后一个匹配信息。

35 $ n($ 1,$ 2,$ 3 ...)

在最后一个模式匹配的第n组中匹配的字符string。相当于m [n],其中m是MatchData对象。

36 $&

在最后一个模式匹配中匹配的字符string。相当于m [0],其中m是MatchData对象。

37 $`

在最后一个模式匹配的匹配之前的字符string。相当于m.pre_match,其中m是MatchData对象。

38 $"

匹配后的字符string在最后一个模式匹配。相当于m.post_match,其中m是MatchData对象。

39 $ +

与最后一个模式匹配的最后一个成功匹配的组对应的字符string。

Ruby - 预定义常量

下表列出了所有Ruby的预定义常量 -

- TRUE,FALSE和NIL都向后兼容。最好使用true,false和nil。

没有 常数名称和描述
1 真正

同义词为真。

2

同义词为虚假。

3

同义词为零。

4 ARGF

如果没有命令行参数,则提供对作为命令行参数传递的文件的虚拟级联访问的对象或标准输入。$的同义词。

5 ARGV

包含传递给程序的命令行参数的数组。$ *的同义词。

6 数据

用于读取__END__指令后面的代码行的输入流。如果__END__不在代码中,则不定义。

7 ENV

包含程序的环境变量的类似哈希的对象。ENV可以作为哈希处理。

8 RUBY_PLATFORM

一个指示Ruby解释器平台的字符string。

9 RUBY_RELEASE_DATE

指示Ruby解释器发布日期的字符string

10 RUBY_VERSION

一个指示Ruby解释器版本的字符string。

11 STDERR

标准错误输出流。$ stderr的默认值

12 STDIN

标准输入流。$ stdin的默认值。

13 STDOUT

标准输出流。默认值$ stdout。

14 TOPLEVEL_BINDING

在Ruby顶级的绑定对象。

Ruby - 相关工具

标准Ruby工具

标准的Ruby发行版包含有用的工具以及解释器和标准库 -

这些工具可帮助您调试和改进Ruby程序,而不用花费太多的精力。本教程将为您提供一个非常好的开始,这些工具。

  • RubyGems -

    RubyGems是一个用于Ruby的软件包实用程序,它可以安装Ruby软件包并保持最新。

  • Ruby调试器 -

    为了帮助处理错误,Ruby的标准发行版包括一个调试器。这与gdb实用程序非常相似,可用于调试复杂程序。

  • 交互式Ruby(irb) -

    irb(Interactive Ruby)由Keiju Ishitsuka开发。它允许您在提示符下输入命令,并让解释器像执行程序一样进行响应。irb可用于实验或探索Ruby。

  • Ruby Profiler -

    通过查找瓶颈,Ruby profiler可以帮助您提高缓慢程序的性能。

其他Ruby工具

还有其他有用的工具不会与Ruby标准分发捆绑在一起。但是,您需要自己安装。

  • eRuby:嵌入式Ruby -

    eRuby stands for embedded Ruby. It"s a tool that embeds fragments of Ruby code in other files, such as HTML files similar to ASP, JSP and PHP.

  • ri: Ruby Interactive Reference

    When you have a question about the behavior of a certain method, you can invoke ri to read the brief explanation of the method.

For more information on Ruby tool and resources, have a look at Ruby Useful Resources.