我发了许多种类和一些陷阱的动物的文字,以及没有意思的其他文字,例如: “cat dog house 131 bird 1341 house trap cat cat cat dog trap house dog house trap
”。
我正在尝试构建一个正则表达式,它将为每个陷阱找到最接近的优先级动物,例如“猫狗屋131 鸟 1341屋 陷阱 猫猫猫狗 陷阱 房子狗房子 陷阱 “。
我写过这个正则表达式:(cat|dog|bird)(?!.*(cat|dog|bird).*).*trap
这是我的完整Java代码:
Pattern p = Pattern.compile("(cat|dog|bird)(?!.*(cat|dog|bird).*).*trap");
Matcher m = p.matcher("cat dog house 131 bird 1341 house trap cat cat cat dog trap house dog house trap");
int start = 0;
while (m.find(start)) {
System.out.println(m.group(0));
System.out.println(m.group(1));
start = m.start + 1; //increment
}
很奇怪它只发现了最后一次骚扰,而不是第一次,第二次和最后一次。上面代码的输出是:
dog house trap
dog
为什么?我试图将^.*?
添加到正则表达式之前将其锚定到开头,但它没有帮助。
答案 0 :(得分:3)
您可以这样做:
Pattern p = Pattern.compile("(cat|dog|bird)((?!cat|dog|bird).)*?trap");
Matcher m = p.matcher("cat dog house 131 bird 1341 house trap cat cat cat dog trap house dog house trap");
while (m.find()) {
System.out.println(m.group(1) + " :: " + m.group(0));
}
产生:
bird :: bird 1341 house trap
dog :: dog trap
dog :: dog house trap
简要说明:
(cat|dog|bird) # match one of: 'cat', 'dog' or 'bird'
( # start group 2
(?!cat|dog|bird). # if none of 'cat', 'dog' or 'bird' are ahead, match any char (except line breaks)
)*? # end group 2 and reluctantly match it zero or more times
trap # match 'trap'
你可以在负面预测中添加trap
,但“不情愿”的量词将导致第一次出现trap
作为结束。< / p>
答案 1 :(得分:2)
这是因为你的表达说动物不能被任何动物所追随。这就是为什么只有最后一只“被困动物”匹配的原因。
这是一个难以解决的问题,因为基本上你想说“之间的某些内容不匹配 bird|dog|cat
”。
我能想到的最好的解决方案就是这个(它并不漂亮!)
import java.util.regex.*;
public class Test {
public static void main(String[] args) {
String pat = "(cat|dog|bird)([^bcd]|b(?!ird)|c(?!at)|d(?!og))*trap";
String str = "cat dog house 131 bird 1341 house trap cat cat cat dog " +
"trap house dog house trap";
Pattern p = Pattern.compile(pat);
Matcher m = p.matcher(str);
int start = 0;
while (m.find(start)) {
System.out.printf("Found trapped %s at %d%n", m.group(1), m.start());
start = m.start() + 1;
}
}
}
<强>输出:强>
Found trapped bird at 18
Found trapped dog at 51
Found trapped dog at 66
基本上它说,
cat|dog|bird
,然后是b
,c
和d
之外的任何字符,或
b
(但未跟ird
)或c
(但未跟at
)或d
(但未跟og
)。trap
答案 2 :(得分:0)
我无法编辑,但在最后一行应该是start = m.start + 1;
。
答案 3 :(得分:0)
正如aioobe所说,解决这个问题很麻烦,只有当您的要求变得更加复杂时,才能通过RegEx解决问题。
(伪代码)的某些内容......
str = "cat dog house 131 bird 1341 house trap cat cat cat dog trap house dog house trap";
arr = str.split(" "); //split on spaces
trapping = null;
for each item in arr {
if (isTrap(item) && trapping != null) {
reportTrappedAnimal(trapping);
trapping = null;
} else if (isAnimal(item)) {
trapping = item;
}
}
您可以使用正则表达式来实现isAnimal()
和isTrap()
,但根据您的要求,这可能是过度或不切实际的。