如何验证字符串是 Ruby 中正确的十六进制值?

Posted

技术标签:

【中文标题】如何验证字符串是 Ruby 中正确的十六进制值?【英文标题】:How to validate that a string is a proper hexadecimal value in Ruby? 【发布时间】:2013-12-22 14:35:51 【问题描述】:

我正在用 Ruby 编写一个 6502 汇编程序。我正在寻找一种以字符串形式验证十六进制操作数的方法。我知道 String 对象提供了一个“十六进制”方法来返回一个数字,但是我遇到了一个问题:

  "0A".hex #=> 10 - a valid hexadecimal value
  "0Z".hex #=>  0 - invalid, produces a zero
"asfd".hex #=> 10 - Why 10?  I guess it reads 'a' first and stops at 's'?

你会通过输入一堆乱码得到一些奇怪的结果。我需要的是一种首先验证该值是否为合法十六进制字符串的方法。

我在玩正则表达式,并意识到我可以做到这一点:

true if "0A" =~ /[A-Fa-f0-9]/
#=> true

true if "0Z" =~ /[A-Fa-f0-9]/
#=> true <-- PROBLEM

我不确定如何解决这个问题。我需要能够验证字母是否只有 A-F,如果只是数字也可以。

我希望避免意大利面条式代码,其中充斥着“if”语句。我希望有人可以提供“单行”或某种形式的优雅代码。

谢谢!

【问题讨论】:

^$ 锚定你的模式,否则,零匹配,Z 不需要匹配。 true if "0Z" =~ /^[A-Fa-f0-9]+$/ @MichaelBerkowski:你应该把它作为答案。 【参考方案1】:

String#hex 不会将整个字符串解释为十六进制,它会从字符串的开头提取直到可以解释为十六进制。对于"0Z""0" 是有效的十六进制,因此它解释了该部分。对于"asfd""a" 是有效的十六进制,因此它解释了该部分。

【讨论】:

【参考方案2】:

!str[/\H/] 将查找无效的十六进制值。

【讨论】:

你碰巧知道是否有与此等效的二进制文件吗? 这在 1.8.7 上不起作用,并且不处理带有“0x”的前导字符串。但仍然很酷。 @AShelly 没什么大不了的:!str.gsub('0x','')[/\H/]【参考方案3】:

一种方法:

str.to_i(16).to_s(16) == str.downcase

另一个:

str =~ /\A[a-f0-9]+\Z/i   # or simply /\A\h+\Z/ (see hirolau's answer)

关于您的正则表达式,您必须使用锚点(\A 表示字符串开头,\Z 表示字符串结尾)来表示您希望整个字符串匹配。此外,+ 会重复匹配一个或多个字符。

请注意,您可以使用^(行首)和$(行尾),但这将允许像"something\n0A" 这样的字符串通过。

【讨论】:

【参考方案4】:

由于 Ruby 内置了十六进制文字,您可以评估字符串并挽救 SyntaxError

eval "0xA" => 10

eval "0xZ" => 语法错误

您可以在类似的方法上使用它

def is_hex?(str)
  begin
    eval("0x#str")
    true
  rescue SyntaxError
    false
  end
end

is_hex?('0A') => true
is_hex?('0Z') => false

当然,既然您使用的是 eval,请确保您只向方法发送安全值

【讨论】:

好主意,但你必须告诉如何根据 OP 提供的字符串来做到这一点。 不知道为什么我得到两个否定,因为我在那里提供了一个完全有效的答案。为了说明我的观点,我将在答案中添加一个方法,看看如何使用它 显然1; "system \"rm -rf /\"; 5" 是一个有效的十六进制数。 :) 好吧,在我刚刚提供的示例方法中,我是说您在进行 eval 时必须小心。这是不言而喻的 这不是一个“坏”的例子,但我希望找到一个开销最小的优雅解决方案。根据我的经验,使用“eval”是最后的手段。【参考方案5】:

这是一个老问题,但我自己也遇到了这个问题。我在我的代码中选择了这个:

str =~ /^\h+$/

如果 str 为 nil,它具有返回 nil 的额外好处。

【讨论】:

以上是关于如何验证字符串是 Ruby 中正确的十六进制值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ruby 中将十进制值数组转换为 MAC 地址?

Redis:十客户端连接

如何将String / char格式化为十六进制值正确

Ruby 将 64 位 IEEE 754 十六进制转换为双精度

Python如何将浮点数作为十六进制转换为十进制

任务十六:零基础JavaScript编码