从散列的内容替换文件中的文本

时间:2019-03-19 23:51:41

标签: ruby

我有一个.TXT,其中填充了以下几行:

January 1987

October 1988

May 1975

,依此类推。我只想用数字格式替换月份名称,例如January将替换为1February的{​​{1}}等。为此,到目前为止,我已经创建了2和以下代码:

hash

2 个答案:

答案 0 :(得分:3)

FILE_IN  = 'foo.txt'
FILE_OUT = 'bar.txt'

首先构造文件。

File.write(FILE_IN, "January 1987\nOctober 1988\nMay 1975\n")
  #=> 35

使用String#gsub和正则表达式来执行替换很方便。下面是我们想要的正则表达式。

r = Regexp.union(dates.keys)
  #=>  /January|February|March|April|May|June|July|August|September|October|November|December/

假设文件不是很大,我们可以内容提取为字符串,使用gsub进行替换,然后将修改后的字符串写入输出文件:

File.write(FILE_OUT, File.read(FILE_IN).gsub(r, dates))
  #=> 22

我们可以通过检查输出文件的内容来看到此方法。

puts File.read(FILE_OUT)
1 1987
10 1988
5 1975

使用String#gsub的形式,该形式采用哈希(dates)进行替换。另请参见IO::readIO::writeIO通常与File作为接收者一起使用。可以,因为FileIOFile.superclass #=> IO)的子类,因此继承了后者的方法。

另请参阅Regexp::union

步骤如下:

s = File.read(FILE_IN)
  #=> "January 1987\nOctober 1988\nMay 1975\n" 
t = s.gsub(r, dates)
  #=> "1 1987\n10 1988\n5 1975\n" 
File.write(FILE_OUT, t

如果文件很大,则需要逐行执行替换。您可以按照以下步骤进行操作。

f = open(FILE_OUT, "w")
File.foreach(FILE_IN) { |line| f.puts(line.gsub(r, dates)) }
f.close

puts File.read(FILE_OUT)
1 1987
10 1988
5 1975

请参见File::openIO#puts IO#closeIO::foreach

请注意,您可以按照以下方式构造哈希dates

require 'date'

Date::MONTHNAMES.each_with_index.drop(1).to_h
  #=> {"January"=>1, "February"=>2, ... , "December"=>12}

当您只写dates时,您可能会认为这很麻烦,但是它确实可以防止拼写和其他可能难以调试的错误。

答案 1 :(得分:1)

这是一种方法:使用正则表达式交替结构(管道|)和单词边界\b以避免匹配,例如Maybe,并将哈希传递到gsub

dates = {
  'January' => 1, 
  'February' => 2, 
  'March'  => 3, 
  'April' => 4, 
  'May' => 5, 
  'June' => 6, 
  'July' => 7, 
  'August' => 8, 
  'September' => 9, 
  'October' => 10, 
  'November' => 11, 
  'December' => 12
}

file_names = ['foo.txt', 'bar.txt']

file_names.each do |file_name|
  text = File.read(file_name)
  new_content = text.gsub(/\b(#{dates.keys.join "|"})\b/, dates)
  File.write(file_name, new_content) # the file will be overwritten
end 

但是,在Ruby中使用日期时,date库在Date::MONTHNAMES中提供了一组日期名称,您可以用来构建哈希:

require 'date'

file_names = ['foo.txt', 'bar.txt']
months = Hash[Date::MONTHNAMES.drop(1).zip 1..12]
pattern = /\b(#{months.keys.join "|"})\b/

file_names.each do |file_name|
  text = File.read(file_name)
  new_content = text.gsub(pattern, months)
  File.write(file_name, new_content)
end