文件操作
我之前说过,正则表达式通常用于处理存储在磁盘上文件中的数据。在一些之前的示例中,我们从磁盘文件中读取数据,进行一些模式匹配并在屏幕上显示结果。这是另一个我们计算文件中单词的示例。通过扫描每一行来创建一个单词数组(即字母数字字符序列)然后将每个数组的大小添加到变量,count
:
wordcount.rb
count = 0
File.foreach( 'regex1.rb' ){ |line|
count += line.scan( /[a-z0-9A-Z]+/ ).size
}
puts( "There are #{count} words in this file." )
我在示例程序中包含了一些可替换代码(被注释掉),它显示每个单词及其编号:
File.foreach( 'regex1.rb' ){ |line|
line.scan( /[a-z0-9A-Z]+/ ).each{ |word|
count +=1
print( "[#{count}] #{word}\n" )
}
}
现在让我们看看如何同时处理两个文件 - 一个用于读取,另一个用于写入。第一个示例打开文件 testfile1.txt 进行写入,并将文件变量 f
传递到块中。我现在打开第二个文件 regex1.rb 进行读取,并使用 File.foreach
将从该文件读取的每行文本传递到第二个块中。我使用一个简单的正则表达式来创建一个新的字符串,以匹配具有 Ruby 风格注释的行;当该字符是一行中的第一个非空白字符时,代码将 Ruby 注释字符('#'
)替换为 C 风格的注释字符('//'
);并将每行写入 testfile1.txt,代码行未经修改(因为没有匹配到)并且注释行更改为 C 风格:
regexp_file1.rb
File.open( 'testfile1.txt', 'w' ){ |f|
File.foreach( 'regex1.rb' ){ |line|
f.puts( line.sub(/(^\s*)#(.*)/, '\1//\2') )
}
}
这说明了使用正则表达式和非常少的编码可以完成多少工作。
下一个示例显示了如何读取一个文件(此处为文件 regex1.rb)并写出两个新文件 - 其中一个(comments.txt)仅包含行注释,而另一个(nocomments.txt)包含文件中所有其它行:
regexp_file2.rb
file_out1 = File.open( 'comments.txt', 'w' )
file_out2 = File.open( 'nocomments.txt', 'w' )
File.foreach( 'regex1.rb' ){ |line|
if line =~ /^\s*#/ then
file_out1.puts( line )
else
file_out2.puts( line )
end
}
file_out1.close
file_out2.close