繁体   English   中英

使用ruby使用正则表达式替换csv中的字符串

[英]Replace a string in csv using regex using ruby

我有一个csv文件,其中具有列test和id,值是:

"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 123 test"替换为"abc is 567 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:调用*的参数数量错误(0表示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|

您想使用以下方法打开原始文件:

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

DATA__END__是访问存储在Ruby脚本末尾的示例数据的方法。)

'123'容易产生假阳性结果,并且会更改子字符串:

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

为了解决这个问题,如果有可能子字符串匹配,则您想使用更智能的搜索字符串; 我会使用正则表达式:

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

现在检查123附近是否有单词边界:

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

由于“ 123”可能会更改,因此将其分配给常量,然后将其替换为模式是有意义的:

TARGET_STR = '123'

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

因为我正在使用带有openforeach的块,所以一旦块结束,Ruby就会自动关闭文件,从而使代码更简洁,并更好地管理文件句柄。

您的代码:

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的文件。 如果您不知道,特别是如果您在文件可能位于GB范围内的生产环境中工作,则使用逐行IO会更快,更安全,因为它避免了可伸缩性问题。 有关更多信息,请参见“ 为什么“悬挂”文件不是一个好习惯? ”。
  • 我们不知道什么是expected_file ,但是由于未定义,它将导致错误,因此Ruby会因为您使用gsub!而反抗gsub! 零值的方法。
  • 如果expected_file是字符串,则expected_file.gsub! 会发生变异expected_file ,但分配结果file_final浪费CPU。 而是重用expected_file ,或者更好地使用:

     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'))

速度没有提高,反而会降低可读性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM