java:使用regex解析重复的子字符串

java:使用regex解析重复的子字符串,java,regex,Java,Regex,这是专门针对解析十六进制字节的,但这里有一个更一般的问题 假设我有一个regexpr例如\\s*([0-9A-Fa-f]{2})\\s*(可选空格,我感兴趣的两个十六进制数字和可选空格) 如果我想用这个regexp解析字符串s,那么: 如果可以将s划分为一系列与r匹配的块,我想为每个块做一些事情。(例如,ff 7c 0903 02BB aC可以这样划分。) 如果s不能被相应地分割,我想检测这个。(例如,00 01 02 hi there ab ff和9 0 2 1 0和Y0 DEADBEEF和

这是专门针对解析十六进制字节的,但这里有一个更一般的问题

假设我有一个regexp
r
例如
\\s*([0-9A-Fa-f]{2})\\s*
(可选空格,我感兴趣的两个十六进制数字和可选空格)

如果我想用这个regexp解析字符串
s
,那么:

  • 如果可以将
    s
    划分为一系列与
    r
    匹配的块,我想为每个块做一些事情。(例如,
    ff 7c 0903 02BB aC
    可以这样划分。)

  • 如果
    s
    不能被相应地分割,我想检测这个。(例如,
    00 01 02 hi there ab ff
    9 0 2 1 0
    Y0 DEADBEEF
    cafe BABE!
    全部失败。)


如何使用Java的regexp工具来实现这一点?

我相信这是一个Java的用例。您可以使用或来发现下一个令牌是否与您的正则表达式匹配

我手边没有编译器,但我想它应该是这样的:

Scanner myScanner = new Scanner(mySource);
// default delimiter is any whitespace, so you don't need to call useDelimiter()
Pattern myPattern = Pattern.compile("\\s*([0-9A-Fa-f]{2})\\s*");
String s = null;
while ((s = myScanner.next(myPattern)) != null) {
    // do something with the token
}

另一种选择是使用正则表达式匹配器和lookingAt()方法

比如:

Pattern p = Pattern.compile( "\\s*([0-9A-Fa-f]{2})" );
Matcher m = p.matcher( myString );
int lastEnd = 0;
while( m.lookingAt() ) {
    System.out.println( "Hex part:" + m.group(1) );
    lastEnd = m.end();
}   
if( lastEnd < myString.length() ) {
    System.err.println( "Encountered non-hex value at index:" + lastEnd );
}
Pattern p=Pattern.compile(\\s*([0-9A-Fa-f]{2})”;
Matcher m=p.Matcher(myString);
int lastEnd=0;
while(m.lookingAt()){
系统输出打印项次(“六角部分:+m组(1));
lastEnd=m.end();
}   
if(lastEnd

……或者别的什么。lookingAt()必须从当前位置开始,因此所有匹配项都必须是连续的。要捕获的唯一错误条件是提前完成,因为这意味着遇到了非十六进制格式的数据。

您可以通过添加锚来检查完整的输入,或者使用
匹配()
而不是
包含()
,regexp变为:

^(\\s*([0-9A-Fa-f]{2}))+\\s*$
如果此rgeexp匹配,则可以继续并迭代以下匹配项:

\\s*([0-9A-Fa-f]{2})

获取十六进制字节。

有趣的是,好的,我如何确保令牌之前/之后/之间没有不匹配的输入?嗯。。。已经有一段时间了,但我认为您必须尝试
hasNext()
skip()
。我们不打算使用2个regexp,但这肯定是简单明了的。这是迄今为止最好的答案,但您正在考虑的另一种方法是
Matcher#find()
contains()
是一个字符串方法,只进行文本搜索。@Alan,谢谢你的评论,我指的是Jakarta ORO方法匹配和contains.neat!我最终手动执行了这种方法(检查前一个end()和当前的start()),不知道lookingAt()。这是不对的
lookingAt()
仅匹配匹配器区域的开头,默认情况下,该区域是字符串的开头。您可以通过不断更改区域的起始边界来实现这种方法,但只需将
\G
前置到正则表达式并使用
find()
就更容易了。实际上,你的代码只是在一个无限循环中不断匹配前两个十六进制数字(如果它匹配任何东西的话),他是对的。我使用lookingAt()实现类似目的的代码每次都会截断字符串。。。这是另一种选择。myString=myString.substring(lastEnd)几乎是免费的。我忘记放了。