我是ruby新手,请原谅我的无知:(
我刚刚了解了eval
,也读到了它的阴暗面。
到目前为止我读到的内容:
-
Ruby中的
eval
何时对正? -
"eval"应该是讨厌的吗?
-
Ruby Eval与Ruby代码的执行
所以我要做的是读取一个文件,其中有一些文本,如/e/ 3
,它将在评估后用3
替换每个e
。
到目前为止我做了什么:(工作,但…(
def evaluate_lines
result="elt"
IO.foreach("test.txt") do |reg|
reg=reg.chomp.delete(' ')
puts reg
result=result.gsub(eval(reg[0..2]),"#{reg[3..reg.length]}" )
p result
end
end
test.txt文件的内容
/e/ 3
/l/ 1
/t/ 7
/$/ !
/$/ !!
这只是因为我知道文件中行的长度。
因此,假设我的文件具有以下/a-z/ 3
,我的程序将无法执行预期的操作
备注
我尝试使用Regexp.new reg
,结果得到了下面的//e/3/
,在这种情况下没有太大帮助。
Regexp 的简单示例
str="/e/3"
result="elt"
result=result.gsub(Regexp.new str)
p result #outputs: #<Enumerator: "elt":gsub(//e/3/)>
我已经尝试过去掉斜线,但即使这样也不能提供所需的结果,因此gsub()
需要两个参数,比如这个gsub(/e/, "3")
。
关于Regexp的用法,我已经阅读了将字符串转换为正则表达式ruby
虽然您可以编写一些东西来解析该文件,但由于必须解析正则表达式,它很快就会变得复杂。以//foo\/
为例。
存在许多不完整的解决方案。您可以在空白处进行拆分,但在/foo bar/
上会失败。
re, replace = line.split(/s+/, 2)
您可以使用正则表达式。这是第一针。
match = "/3/ 4".match(%r{^/(.*)/s+(.+)})
这在转义的/
上失败了,我们需要更复杂的东西。
match = '/3// 4'.match(%r{A / ((?:[^/]|\/)*) / s+ (.+)}x)
我想这不是你的老师的意图,让你解析正则表达式。出于赋值的目的,在空白处进行拆分可能很好。你应该向你的老师澄清。
这是一种糟糕的数据格式。它是非标准的,很难解析,并且在替换方面有局限性。即使是制表符分隔的文件也会更好。
现在几乎没有理由使用非标准格式。最简单的方法是对文件使用标准的数据格式。YAML或JSON是最明显的选择。对于这样简单的数据,我建议使用JSON。
[
{ "re": "e", "replace": "3" },
{ "re": "l", "replace": "1" }
]
解析文件很简单,请使用内置的JSON库。
require 'json'
specs = JSON.load("test.json")
然后,您可以将它们用作哈希列表。
specs.each do |spec|
# No eval necessary.
re = Regexp.new(spec["re"])
# `gsub!` replaces in place
result.gsub!(re, spec["replace"])
end
数据文件是可扩展的。例如,如果以后要添加regex选项。
[
{ "re": "e", "replace": "3" },
{ "re": "l", "replace": "1", "options": ['IGNORECASE'] }
]
虽然老师可能指定了一个糟糕的格式,但作为一名开发人员,抵制糟糕的要求是一种很好的做法。
这里有一个非常简单的例子,它使用vi
表示法,如s/.../.../
和s/.../.../g
:
def rsub(text, spec)
_, mode, repl, with, flags = spec.match(%r[A(.)/((?:[^/]|\/)*)/((?:[^/]|\/)*)/(w*)z]).to_a
case (mode)
when 's'
if (flags.include?('g'))
text.gsub(Regexp.new(repl), with)
else
text.sub(Regexp.new(repl), with)
end
end
end
请注意,匹配器查找非斜杠字符([^/]
(或一个字面斜杠组合(\/
(,并相应地将这两部分分开。
在哪里你可以得到这样的结果:
rsub('sandwich', 's/and/or/')
# => "sorwich"
rsub('and/or', 's///,/')
# => "and,or"
rsub('stack overflow', 's/o/O/')
# => "stack Overflow"
rsub('stack overflow', 's/o/O/g')
# => "stack OverflOw"
这里的原理是,您可以使用一个非常简单的正则表达式来解析输入的正则表达式,并将清理后的数据馈送到Regexp.new
中。这里绝对不需要eval
,如果有什么严重限制你可以做的话。
只需做一点工作,您就可以更改正则表达式来解析现有文件中的内容,并使其执行您想要的操作。