如何验证字符串是 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 中正确的十六进制值?的主要内容,如果未能解决你的问题,请参考以下文章