2017-05-24 21 views
0

我有有一个列测试一个CSV文件,身份证件和值替换CSV字符串:使用正则表达式使用Ruby

"abc is 123 test", 1 

"abc is 123 test", 2 

"abc is 123 test", 3 

"abc is 123 test", 4 

"abc is 123 test", 5 

我想"abc is 567 test"更换"abc is 123 test"

注:值123567是动态值,与每一个新的CSV 123得到改变,但串"abc is <value> test"始终保持不变。

代码我想:

folder_path = "/home/test/files/" 
f1 = folder_path + "abc.csv" 
string_replace = "abc is 567 test" 

file = IO.read(/home/test/files/abc.csv") 
file_final = expected_file.gsub!("abc is".*, string_replace) 
File.open(f1, 'w') { |f| f.write(file_final) } 

我收到错误:

"ArgumentError: wrong number of arguments calling * (0 for 1)

谁能帮助?

+0

它可以是多于3位数字或不到3个数字为好。 – rubyUser

+0

“abc是123测试”中的数字总是三位数? –

+0

使用'read'和正则表达式是一个坏主意,除非你总是知道该文件很容易装进内存。与使用逐行IO相比,超过2MB的任何内容都会使您的代码变慢。 https://stackoverflow.com/questions/25189262/ –

回答

1

虽然技术上文件是CSV文件,但我们可以将CSV文件视为文本,因为这就是它们。当他们很简单时,这可以让他们更容易。

我开始:

File.open('csv.new', 'w') do |fo| 
    DATA.each_line do |li| 
    fo.puts li.sub('123', '456') 
    end 
end 

__END__ 
"abc is 123 test", 1 
"abc is 123 test", 2 
"abc is 123 test", 3 
"abc is 123 test", 4 
"abc is 123 test", 5 

运行它会生成一个名为 “csv.new” 文件,其中包含:

"abc is 456 test", 1 
"abc is 456 test", 2 
"abc is 456 test", 3 
"abc is 456 test", 4 
"abc is 456 test", 5 

相反的:

DATA.each_line do |li| 

你” d要使用以下方式打开原始文件:

File.foreach("/home/test/files/abc.csv") do |li| 

DATA__END__是访问存储在一个Ruby脚本的末尾采样数据的一种方式。)

'123'容易出现假阳性命中,并且将改变的子串:

''.sub('123', '456') # => "0456456" 

为了反击这一点,如果有任何机会的子串匹配,你想使用更智能的搜索字符串;我会使用一个正则表达式:

''.sub(/\b123\b/, '456') # => "" 

现在检查,看看是否有周围123一个字边界:

'0 123 456'.sub(/\b123\b/, '456') # => "0 456 456" 

由于“123”可能会改变,它会是有意义的给它分配到恒定则替换该入模式:

TARGET_STR = '123' 

''.sub(/\b#{TARGET_STR}\b/, '456') # => "" 
'0 123 456'.sub(/\b#{TARGET_STR}\b/, '456') # => "0 456 456" 

因为我使用的块与openforeach,红宝石自动将一旦块结束,关闭文件,导致更简洁的代码,并更好地管理文件句柄。

您的代码:

file = IO.read(/home/test/files/abc.csv") 
file_final = expected_file.gsub!("abc is".*, string_replace) 
File.open(f1, 'w') { |f| f.write(file_final) } 

...是一个...混乱。

  • read对于你知道文件总是小于1MB的文件来说很棒。如果你不知道,特别是如果你在生产环境中工作,其中的文件可以顺利进入国标范围内,使用行由行IO速度更快,因为它回避可扩展性问题更安全。有关更多信息,请参阅“Why is "slurping" a file not a good practice?”。
  • 我们不知道什么是​​,而是因为它是未定义因此Ruby会造反,因为你使用的gsub!方法在零值,它会导致错误。
  • 如果​​是一个字符串,expected_file.gsub!会变异​​,但将结果分配给file_final会浪费CPU。相反重用​​,或者更好的,使用方法:

    file_final = expected_file.gsub(
    
  • "abc is".*是一个无效的参数。可能"abc is.*"就会更接近,但它似乎你达到了一个正则表达式/abc is.*/,但就没有必要改变字符串,/123/'123'就足够了。

  • gsub在这里也是过分的,因为您只需要一个替换,所以sub会更快。
  • 技术上,

    File.open(f1, 'w') { |f| f.write(file_final) } 
    

    的工作,但它更容易写成

    File.write(f1, file_final) 
    

您可以将代码简化为:

File.write(
    'file.csv.new', 
    File.read('file.csv').gsub(/\b123\b/, '456') 
) 
其中,出乖张的,可以写成

File.write('file.csv.new', File.read('file.csv').gsub(/\b123\b/, '456')) 

有会是在速度上没有改善,反而它会降低可读性。