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

时间:2013-12-05 15:14:54

标签: ruby regex hex

我正在用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,如果它只是数字也可以。

我希望避免意大利面条代码,充斥着“如果”的陈述。我希望有人可以提供“单行”或某种形式的优雅代码。

谢谢!

5 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:3)

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

答案 2 :(得分:1)

一种方法:

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"等字符串。

答案 3 :(得分:0)

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

str =~ /^\h+$/

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

答案 4 :(得分:-2)

由于Ruby内置了文字十六进制,因此您可以评估该字符串并解除SyntaxError

eval“0xA”=&gt; 10

eval“0xZ”=&gt;的SyntaxError

您可以在类似

的方法上使用此功能
def is_hex?(str)
  begin
    eval("0x#{str}")
    true
  rescue SyntaxError
    false
  end
end

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

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