使用ruby使用regex替换csv中的字符串
我有一个csv文件,其中有一个列test和id,值为:使用ruby使用regex替换csv中的字符串,ruby,string,csv,Ruby,String,Csv,我有一个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 567 test”替换“abc is 123 test” 注意:值123和567是动态值,随着每个新csv123的更改,但字符串“abc是测试”始终保持不变 我试过的代码: folder_path =
"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”
注意:值123
和567
是动态值,随着每个新csv123
的更改,但字符串“abc是测试”
始终保持不变
我试过的代码:
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
和是访问存储在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"
因为我使用的块带有open
和foreach
,所以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\u file
是什么,但它会导致错误,因为它未定义,所以Ruby会反抗,因为您对nil值使用了gsub!
方法
- 如果
expected\u file
是一个字符串,expected\u file.gsub!
将变异expected\u file
,但将结果分配给file\u final
会浪费CPU。相反,请重新使用expected\u 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'))
速度不会提高,反而会降低可读性。它可以大于3位,也可以小于3位。“abc is 123测试”中的数字是多少“始终是三位数?使用读取和正则表达式是个坏主意,除非您总是知道文件很容易放入内存。与使用逐行IO相比,任何超过2MB的内存都会降低代码的速度。