文件操作

我之前说过,正则表达式通常用于处理存储在磁盘上文件中的数据。在一些之前的示例中,我们从磁盘文件中读取数据,进行一些模式匹配并在屏幕上显示结果。这是另一个我们计算文件中单词的示例。通过扫描每一行来创建一个单词数组(即字母数字字符序列)然后将每个数组的大小添加到变量,count

wordcount.rb
  1. count = 0
  2. File.foreach( 'regex1.rb' ){ |line|
  3. count += line.scan( /[a-z0-9A-Z]+/ ).size
  4. }
  5. puts( "There are #{count} words in this file." )

我在示例程序中包含了一些可替换代码(被注释掉),它显示每个单词及其编号:

  1. File.foreach( 'regex1.rb' ){ |line|
  2. line.scan( /[a-z0-9A-Z]+/ ).each{ |word|
  3. count +=1
  4. print( "[#{count}] #{word}\n" )
  5. }
  6. }

现在让我们看看如何同时处理两个文件 - 一个用于读取,另一个用于写入。第一个示例打开文件 testfile1.txt 进行写入,并将文件变量 f 传递到块中。我现在打开第二个文件 regex1.rb 进行读取,并使用 File.foreach 将从该文件读取的每行文本传递到第二个块中。我使用一个简单的正则表达式来创建一个新的字符串,以匹配具有 Ruby 风格注释的行;当该字符是一行中的第一个非空白字符时,代码将 Ruby 注释字符('#')替换为 C 风格的注释字符('//');并将每行写入 testfile1.txt,代码行未经修改(因为没有匹配到)并且注释行更改为 C 风格:

regexp_file1.rb
  1. File.open( 'testfile1.txt', 'w' ){ |f|
  2. File.foreach( 'regex1.rb' ){ |line|
  3. f.puts( line.sub(/(^\s*)#(.*)/, '\1//\2') )
  4. }
  5. }

这说明了使用正则表达式和非常少的编码可以完成多少工作。

下一个示例显示了如何读取一个文件(此处为文件 regex1.rb)并写出两个新文件 - 其中一个(comments.txt)仅包含行注释,而另一个(nocomments.txt)包含文件中所有其它行:

regexp_file2.rb
  1. file_out1 = File.open( 'comments.txt', 'w' )
  2. file_out2 = File.open( 'nocomments.txt', 'w' )
  3. File.foreach( 'regex1.rb' ){ |line|
  4. if line =~ /^\s*#/ then
  5. file_out1.puts( line )
  6. else
  7. file_out2.puts( line )
  8. end
  9. }
  10. file_out1.close
  11. file_out2.close