今天用Ruby写了以下代码并进行了测试:
#正则表达式
line = gets
if line =~ /Perl|Python/ #如果在字符串中匹配了模式,=~返回字符串中匹配模式的开始位置
puts "Scripting language mentioned: #{line}"
end
我认为/Perl|Python/的意思是匹配"Perl"或者匹配"Python",但是当字符串中既存在"Perl"又存在"Python"时结果如何呢?
我猜想Perl和Python谁在前面(指的是在待匹配字符串中的顺序而非/Perl|Python/中的顺序)就匹配谁,比如"PerlPython"就应当匹配Perl,"PythonPerl"就应当匹配Python。
测试结果如下:
#input: PythonPerl
#output: Scripting language mentioned: PythonPerl
#input: PerlPython
#output: Scripting language mentioned: PerlPython
#input: Perl455Python
#output: Scripting language mentioned: Perl455Python
难道既有Perl又有Python的时候会进行两次匹配?!怀着疑问又进行了如下测试:
#input: Perl1
#output: Scripting language mentioned: Perl1
#input: 1Perl
#output: Scripting language mentioned: 1Perl
咦,这是怎么回事?仔细思考后发现了问题所在,代码的第二行如下:
if line =~ /Perl|Python/ #如果在字符串中匹配了模式,=~返回字符串中匹配模式的开始位置
这就是我开始犯错的地方,我认为如果匹配成功,那么ruby会将匹配的字符串返回给line,但实际上:
- 在我的这几行代码里,line的值从键盘读取了什么就是什么,从未改变过(=是赋值,=~是判断是否匹配)
- =~返回的是字符串中匹配模式的开始位置,并不是匹配的字符串,因此我这个例子无法测试Perl和Python都存在的情况是否两个都匹配(实际上是只匹配一个,是或的关系)
- 表达式 line =~ /Perl|Python/ 的值才是 =~ 最终返回的值,要么是nil,要么是字符串中匹配模式的开始位置
测试代码改版:
line = gets
if line =~ /Perl|Python/ #匹配Perl或者Python,两者其中一个匹配成功即结束,否则匹配失败
puts line =~ /Perl|Python/ #如果在字符串中发现了模式,=~返回(也即表达式line =~ /Perl|Python/的返回值)模式的开始位置
puts "Scripting language mentioned: #{line}"#line的值始终为键盘输入的内容,从未改变过
end
#input: 1Perl
#output:
1
Scripting language mentioned: 1Perl
折腾了半天,以上代码并不能测试我想要测试的内容,反而我对 =~ 的理解更加深入了,又或者说我真正明白了上面这段代码的意思,也是不亦乐乎~