检查字符串是否仅包含十六进制字符的正则表达式

51

我以前从来没用过正则表达式,但我知道它们对于处理字符串非常有用。我看了几个教程(例如),但我仍然不明白如何在Java中使用简单的正则表达式检查字符串中的十六进制字符。

用户将在文本框中输入类似于:0123456789ABCDEF,我想知道输入是否正确,否则如果输入类似于XTYSPG456789ABCDEF,则返回false。

是否可以使用正则表达式实现这一点,还是我对它们的工作方式存在误解?

3个回答

132

你可以使用正则表达式来实现该功能:

^[0-9A-F]+$

解释:

^            行首。
[0-9A-F]     字符类:匹配 0 到 9 或 A 到 F 中的任一字符。
+            量词:匹配一个或多个字母数字字符。
$            行尾。

在Java中,你可以通过在字符串上调用 matches 方法来使用这个正则表达式:

boolean isHex = s.matches("[0-9A-F]+");
注意,matches仅匹配完全相同的字符串,所以在这种情况下您不需要行首和行尾锚点。在线演示请参见:ideone 如果您还想允许大写字母A到F,则可以使用以下正则表达式:
^[0-9A-Fa-f]+$

2
如果要允许小写字母i,应该这样做 ^[0-9a-fA-F]+$?那么如何实现呢?我的意思是这样正确吗 if(labelA.getText().equals(^[0-9A-F]+$)) {...}?非常感谢您的帮助。 - pondigi
1
如果您要多次使用相同的测试,则编译一次模式(Pattern hex = Pattern.compile("^[0-9A-F]+$")),然后通过 hex.matcher(string).matches() 进行测试会更有效率。 - Paŭlo Ebermann
1
顺便提一下,^$锚点在这里并不必要,因为matches()总是匹配整个字符串。 - Paŭlo Ebermann
回复这个评论有点晚了。但我尝试了上面的解决方法,当字符串以"0x"开头时,它会失败。我尝试了 ^(0x|0X)?[0-9A-Fa-f]+$" 但它也失败了... 能帮忙吗 :( - Udayaditya Barua
2
@Uday:创建一个新问题。您需要提供更多关于您正在做什么的信息。在创建您的问题时,请记得包括您正在使用的编程语言、您已经编写的代码、您正在测试的输入字符串、实际发生了什么以及您想要发生什么等等。您提供的信息越多,就越有可能有人能够帮助您。 - Mark Byers
优美且简洁的正则表达式解决方案 - laycat

30

也许你想使用POSIX字符类\p{XDigit},因此:

^\p{XDigit}+$

此外,如果您计划经常使用该正则表达式,则建议使用常量以避免每次重新编译它,例如:

private static final Pattern REGEX_PATTERN = 
        Pattern.compile("^\\p{XDigit}+$");

public static void main(String[] args) {
    String input = "0123456789ABCDEF";
    System.out.println(
        REGEX_PATTERN.matcher(input).matches()
    );  // prints "true"
}

1
这应该是被接受的答案,因为\p{XDigit}是预定义的。 - juanmirocks

13

实际上,给出的答案并不完全正确。问题在于数字 0-9 也是十进制数值。你需要做的部分工作是测试 00-99 而不仅仅是 0-9,以确保较低的值不是十进制数。像这样:

^([0-9A-Fa-f]{2})+$
要说这些东西必须成对出现!否则,这个字符串就会变成其他东西!:-)
例子:
   (Pick one)
   var a = "1e5";
   var a = "10";
   var a = "314159265";

如果我在正则表达式中使用被接受的答案,它会返回TRUE。

   var re1 = new RegExp( /^[0-9A-Fa-f]+$/ );
   var re2 = new RegExp( /^([0-9A-Fa-f]{2})+$/ );

   if( re1.test(a) ){ alert("#1 = This is a hex value!"); }
   if( re2.test(a) ){ alert("#2 = This IS a hex string!"); }
     else { alert("#2 = This is NOT a hex string!"); }

请注意,无论哪种情况下,“10”都返回TRUE。 如果输入的字符串只包含0-9,则不能轻易地确定它是十六进制值还是十进制值,除非在长度不足的字符串前面缺少零(十六进制值总是成对出现-即低字节/高字节)。 但像“34”这样的值既是完全有效的十进制数也是十六进制数。 它们只是表示两个不同的意思。

还要注意,“3.14159265”不是十六进制值,无论进行哪种测试,因为有句号存在。 但是通过添加“{2}”,您至少可以确保它确实是一个十六进制字符串,而不是类似于十六进制字符串的其他内容。


1
我认为这与问题略有偏差,因为它没有提到字节对。验证完全取决于您所需的十六进制表示形式。129h和ACEh都是有效的十六进制数字,只是它们不是有效的字节对。 - mskfisher
另外,3.14159265也是一个有效的十六进制实数 - mskfisher
实际上,仅仅因为我没有使用你的术语(即:字节对),并不意味着我没有说过它(注意:“要说这些必须成对出现!”)。你正在使用不同的方法(即:###h)。 “h”表示它是十六进制(对你来说),对我来说0x##表示十六进制。因此,在Javascript中的129h可能或可能不意味着十六进制值,就像0x##可以表示十六进制值一样。 - Mark Manning
“3.14159265”这个值过去并不意味着它是一个十六进制值。实际上,会发生的是它会在小数点后面截断。现在它可能意味着一个十六进制值,但事实上,十六进制不处理分数,只处理整数。你能否提供一个链接,仅使用纯JavaScript,例如“var a = 3.14152965;”,然后将其显示为十六进制值。没有函数。没有库。谢谢! :-) - Mark Manning

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接