eval certain regex from file to replace chars in string
我是 ruby?? 新手,所以请原谅我的无知 :)
我刚刚了解了 eval 并且读到了它的阴暗面。
到目前为止我读过的内容:
-
Ruby 中的 eval 什么时候是合理的?
-
\\’eval\\’ 应该是讨厌的吗?
-
Ruby Eval 和 Ruby 代码的执行
所以我要做的是读取一个文件,其中有一些文本,例如 /e/ 3 它将在评估后将每个 e 替换为 3。
所以到目前为止我做了什么:(工作但是..)
1
2 3 4 5 6 7 8 9 |
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 文件的内容
1
2 3 4 5 |
/e/ 3
/l/ 1 /t/ 7 /$/ ! /$/ !! |
这只是因为我知道文件中行的长度。
所以假设我的文件具有以下 /a-z/ 3 我的程序将无法执行预期的操作。
笔记
我尝试使用 Regexp.new reg 并导致以下 /\\/e\\/3/ 在这种情况下不是很有帮助。
`Regexp
的简单示例
1
2 3 4 |
str=“/e/3”
result=“elt” result=result.gsub(Regexp.new str) p result #outputs: #<Enumerator:”elt”:gsub(/\\/e\\/3/)> |
我已经尝试去除斜线,但即使这不会提供所需的结果,因此 gsub() 需要两个参数,例如这个 gsub(/e/,”3″).
关于 Regexp 的用法,我已经阅读 Convert a string to regular expression ruby??
- 当你有 Regex.new 时你不需要 eval。我也远离命名您的输入文件 .rb 因为它肯定不是 Ruby 代码。为了使它与 Regexp.new 一起工作,首先去掉前导和尾随斜杠。
- @tadman,这是我的错,我输入的是 rb 而不是 txt 抱歉。我编辑了帖子。无论如何,使用 regexp.new 没有帮助,因此我会给我不想要的结果,因为方法 gsub 需要两个参数,例如 gsub(/e/,”3″)
- 您可以控制输入文件的格式吗?如果是这样,你可以让你的生活轻松一百倍。
- 好吧,虽然我可以完全控制这个文件,但格式是由分配者给出的。这不在桌面上,因此 test.txt 在测试时可能会更大:)。再次,即使我可以去掉反斜杠,我也必须将第二个参数提供给 gsub 方法
虽然您可以编写一些东西来解析该文件,但它很快就会变得复杂,因为您必须解析正则表达式。考虑 /\\/foo\\\\/.
有许多不完整的解决方案。您可以在空格上拆分,但这会在 /foo bar/.
上失败
1
|
re, replace = line.split(/\\s+/, 2)
|
您可以使用正则表达式。这是第一次刺伤。
1
|
match =“/3/ 4”.match(%r{^/(.*)/\\s+(.+)})
|
这在转义 / 上失败,我们需要更复杂的东西。
1
|
match = ‘/3\\// 4′.match(%r{\\A / ((?:[^/]|\\\\/)*) / \\s+ (.+)}x)
|
我猜你老师的意图不是让你解析正则表达式。出于分配的目的,在空格上拆分可能没问题。你应该和你的老师澄清一下。
这是一种糟糕的数据格式。它是非标准的,难以解析,并且在替换上有限制。即使是制表符分隔的文件也会更好。
现在几乎没有理由使用非标准格式。最简单的事情是为文件使用标准数据格式。 YAML 或 JSON 是最明显的选择。对于这样简单的数据,我建议使用 JSON.
1
2 3 4 |
[
{“re”:“e”,“replace”:“3” }, {“re”:“l”,“replace”:“1” } ] |
解析文件很简单,使用内置的 JSON 库。
1
2 |
require ‘json’
specs = JSON.load(“test.json”) |
然后您可以将它们用作哈希列表。
1
2 3 4 5 6 7 |
specs.each do |spec|
# No eval necessary. re = Regexp.new(spec[“re”]) # `gsub!` replaces in place |
数据文件是可扩展的。例如,如果稍后您想添加正则表达式选项。
1
2 3 4 |
[
{“re”:“e”,“replace”:“3” }, {“re”:“l”,“replace”:“1”,“options”: [‘IGNORECASE’] } ] |
虽然老师可能指定了一个糟糕的格式,但对糟糕的要求提出回避是作为开发人员的好习惯。
- 感谢您努力帮助人类。关于你的代码的小闲聊:作为一名学生和 ruby?? 初学者,我还没有使用过 JSON 库。但看看你的代码,我有点明白你答案的 JSON 部分发生了什么。所以,让我看看我是否明白这一点: 1.你会重写 test.txt 文件中的所有修改并将其放入不同格式的 JSON 文件中吗? 2.您会从txt中获取数据并将其放入哈希中然后遍历它吗?那么那些 [ {“re”:”e”,”replace”:”3″ }, {“re”:”l”,”replace”:”1″ } ] 写在哪里?
- 无论如何,我会再次要求教授更好地了解他的意图,然后我可以看看这个答案是否是答案,但现在我非常感谢你的帮助和 1
- @studentaccount4 是的,如果这是生产,我会将文件更改为 JSON。你可以像我一样手动翻译。或者,既然数据这么简单,就用正则表达式解析原始文件,放入合理的数据结构,用JSON.dump写成JSON。因为这是一项作业,所以是的,问问你的教授他们想让你做什么。
这是一个非常简单的例子,它使用 s/…/…/ 和 s/…/…/g 之类的 vi 表示法:
1
2 3 4 5 6 7 8 9 10 11 12 |
def rsub(text, spec)
_, mode, repl, with, flags = spec.match(%r[\\A(.)\\/((?:[^/]|\\\\/)*)/((?:[^/]|\\\\/)*)/(\\w*)\\z]).to_a case (mode) |
请注意,匹配器会查找非斜线字符 ([^/]) 或文字-斜线组合 (\\\\/) 并相应地拆分这两部分。
你可以在哪里得到这样的结果:
1
2 3 4 5 6 7 8 9 10 11 |
rsub(‘sandwich’, ‘s/and/or/’)
# =>”sorwich” rsub(‘and/or’, ‘s/\\//,/’) rsub(‘stack overflow’, ‘s/o/O/’) rsub(‘stack overflow’, ‘s/o/O/g’) |
这里的原则是您可以使用一个非常简单的正则表达式来解析您输入的正则表达式并将清理后的数据输入到 Regexp.new 中。这里绝对不需要 eval ,如果有任何严重限制你可以做的事情。
通过一些工作,您可以更改该正则表达式以解析现有文件中的内容并使其执行您想要的操作。
- 好吧,这看起来很酷,我想我在这里得到了你想要完成的任务,但我有一个关于 _, 这是干什么用的小问题?!另外,看看你写的代码我有一个小问题,请原谅我的无知,spec.match 的返回值是如何在模式、repl 和 with 之间分布的?!请您这么好心,并详细解释 rsub() 的第二行中发生的事情,否则这应该会有所帮助:)
- 在 Ruby 中,_ 是一个”不关心”变量。第一个元素无关紧要,它是所有匹配项的集合。至于解释,对你来说不能太简单,那里有很多事情要做,但如果你把它分解并在 irb 中尝试那行,它会更有意义。
来源:https://www.codenong.com/61719344/