从 string.start_with 得到相同的结果?和字符串[]

Get the same results from string.start_with? and string[ ]

基本上,我想使用上述两种方法检查一个字符串 (main) 是否以另一个字符串 (sub) 开头。例如,以下是我的代码:

main = gets.chomp
sub = gets.chomp

p main.start_with? sub
p main[/^#{sub}/]

而且,这里有一个 I/O - Try it online!

的例子

如果我输入简单的字符串,那么它们的工作原理完全一样,但是当我在stdin中输入像"1"这样的字符串时,我在 Regexp 变体中出现错误,如 TIO 示例所示。

我想这是因为传递给第二个的字符串不是 raw 的原因。所以,我尝试将 sub.dump 传递给第二个 - Try it online!

这给了我 nil 结果。如何正确执行此操作?

作为一般规则,您应该永远不要盲目地执行来自不受信任来源的输入。

将不受信任的输入插入 Regexp 文档中的 Regexp is not quite as bad as interpolating it into, say, Kernel#eval, because the worst thing an attacker can do with a Regexp is to construct an Evil Regex to conduct a Regular expression Denial of Service (ReDoS) attack (see also the section on Performance),而使用 eval,它们可以执行任意代码,包括但不限于删除整个文件系统,扫描内存以获取未加密的密码/信用卡信息/PII 并通过网络将其泄露等

但是,这仍然是个坏主意。例如,当我说“发生的最糟糕的事情是 ReDoS”时,假设 Regexp 实现(Onigmo in the case of YARV, Joni in the case of JRuby and TruffleRuby 等)Ruby 中没有错误 Regexps 非常强大,因此 Onigmo、Joni 和合作伙伴。是大而复杂的代码段,很可能有自己的安全漏洞,可以被特制的 Regexp.

使用

在 构造Regexp 之前,您应该正确清理和转义用户输入。值得庆幸的是,Ruby 核心库已经包含了一个可以做到这一点的方法:Regexp::escape。所以,你可以这样做:

p main[/^#{Regexp.escape(sub)}/]

您尝试使用 String#dump 失败的原因是,String#dump 用于表示 String,就像您必须将其写成 String 文字,即转义 String 元字符,而不是 Regexp 元字符 and 它包括 String 周围的引号字符,您需要将其识别为 String 文字。当你简单地尝试一下时,你可以很容易地看到:

sub.dump
#=> "\"1\\2\""
# equivalent to '"1\2"'

所以,这意味着 String#dump

  • 包括引号(您不需要),
  • 转义不需要在 Regexp 中转义的字符,因为它们需要在 String 中转义(例如 #"),以及
  • 不会 转义不需要在 String 秒内转义的字符(例如 [.?, *, +, ^, -).