使用正则表达式替换具有特定格式的字符串 - Ruby

时间:2014-03-13 06:51:11

标签: ruby regex hash

这是我的代码如下。 我有大约100个文本文件,我想以特定格式替换大量字符串,其中包含与哈希映射中的键相对应的值。

如果你看一下下面的代码,你可以理解这个场景。

require 'yaml'

map = YAML.load(File.open("/Documents/final.yml"))

Dir.glob('/Documents/**/*.txt') do |item|
   next if item == '.' or item == '..'
contents = File.read(item)
newFile = File.open(item, "w")
contents  = contents.gsub(/My data\(@"([^"]+)",([^,]+),([^,]+),([^,]+)\)/) {'Your data(@'+ $1 +','+ $2 +',' + $3 + ',' + map[$1] + ',' + $4 + ')'}
newFile.write(contents)
end

由于某种原因我收到如下错误[test2.rb是我的ruby脚本文件]

test2.rb:9:in `+': no implicit conversion of nil into String (TypeError)
from test2.rb:9:in `block (2 levels) in <main>'
from test2.rb:9:in `gsub'
from test2.rb:9:in `block in <main>'
from test2.rb:5:in `glob'
from test2.rb:5:in `<main>'

如果我从代码中删除地图[$ 1],我会正确地获得输出。

contents  = contents.gsub(/My data\(@"([^"]+)",([^,]+),([^,]+),([^,]+)\)/) {'Your data(@'+ $1 +','+ $2 +',' + $3 + ',' + $4 + ')'}

此外,如果我删除其他字符串并且只有map [$ 1],我仍然会得到预期的输出。

contents  = contents.gsub(/My data\(@"([^"]+)",([^,]+),([^,]+),([^,]+)\)/) { map[$1] }

但它在一起却无效。

任何帮助将不胜感激

2 个答案:

答案 0 :(得分:2)

为了扩展@ NeilSlater的答案,这将是一个可能的清洁解决方案:

contents.gsub(/My data\(@"([^"]+)",([^,]+),([^,]+),([^,]+)\)/) do
  values = [$1, $2, $3, map[$1], $4].join(',')
  "Your data(@#{values})"
end

在这种情况下,join将隐式调用数组内容上的to_s。但是,这意味着如果在map中找不到值,则最终会得到一个空值,例如

  

您的数据(@ 123,a,b,c)

如果你想省略这一点,请在加入之前调用阵列上的compact,最后你会得到

  

您的数据(@ 123,a,b,c)

答案 1 :(得分:1)

对于其中一个文件中的至少一个条目,map[$1]的值为nil。它本身可以存储在一个数组中并根据需要输出。使用+进行连接时,会导致您看到的错误。

您可以使用map[$1].to_s强制转换为字符串。对于nil,这将返回空字符串"",这可能是您想要的。

您还可以使用Ruby的内置字符串插值,它在内部执行相同的操作,并且与您的使用非常匹配 - .gsub之后的块可能是{ "Your data(@#{$1},#{$2},#{$3},#{map[$1]},#{$4})" }