Java—获取两个字符串之间所有字符串的最佳方法?(正则表达式?)
这个问题困扰了我很长一段时间,但本质上我正在寻找最有效的方法来抓取两个字符串之间的所有字符串 我已经这样做了好几个月了,现在是通过使用一堆临时索引、字符串、子字符串,这真的很混乱。(为什么Java没有本机方法,例如Java—获取两个字符串之间所有字符串的最佳方法?(正则表达式?),java,regex,string,Java,Regex,String,这个问题困扰了我很长一段时间,但本质上我正在寻找最有效的方法来抓取两个字符串之间的所有字符串 我已经这样做了好几个月了,现在是通过使用一堆临时索引、字符串、子字符串,这真的很混乱。(为什么Java没有本机方法,例如字符串子字符串(字符串开始,字符串结束) 假设我有一个字符串: abcabc[pattern1]foo[pattern2]abcdefg[pattern1]bar[pattern2]morestuff 最终目标是输出foo和bar(稍后添加到JList中) 我一直试图在.split()
字符串子字符串(字符串开始,字符串结束)
假设我有一个字符串:
abcabc[pattern1]foo[pattern2]abcdefg[pattern1]bar[pattern2]morestuff
最终目标是输出foo
和bar
(稍后添加到JList中)
我一直试图在.split()
中合并正则表达式,但没有成功。我尝试了使用*
和
的语法,但我不认为这完全是我的意图,特别是因为.split()
只需要一个参数来进行拆分
否则,我认为另一种方法是使用Pattern和Matcher类?但我对适当的过程非常模糊。这里有一个一行程序,它可以完成所有工作:
List<String> strings = Arrays.asList( input.replaceAll("^.*?pattern1", "")
.split("pattern2.*?(pattern1|$)"));
输出:
[foo, bar]
您可以构造正则表达式来执行以下操作:
// pattern1 and pattern2 are String objects
String regexString = Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2);
这将把pattern1
和pattern2
视为literal文本,模式之间的文本将在第一个文本中捕获。如果要使用regex,可以删除,但我不保证这样做
通过向regexString
添加标志,可以添加一些匹配方式的自定义
- 如果您想要识别Unicode不区分大小写的匹配,那么在
的开头添加regexString
,或者为方法提供(?iu)
标志Pattern.case不区分大小写| Pattern.Unicode_case
- 如果要捕获内容,即使两个分隔字符串跨行出现,也要在
之前添加(.*)
,即(?s)
,或为方法提供标志“(?s)(?”
列表中(或任何集合中,由您决定)
测试代码:
String pattern1 = "hgb";
String pattern2 = "|";
String text = "sdfjsdkhfkjsdf hgb sdjfkhsdkfsdf |sdfjksdhfjksd sdf sdkjfhsdkf | sdkjfh hgb sdkjfdshfks|";
Pattern p = Pattern.compile(Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2));
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group(1));
}
请注意,如果使用上述方法在此输入foo text foo text bar text bar
中搜索foo
和bar
之间的文本,您将获得一个匹配项,即text foo text尝试以下操作:
String str = "its a string with pattern1 aleatory pattern2 things between pattern1 and pattern2 and sometimes pattern1 pattern2 nothing";
Matcher m = Pattern.compile(
Pattern.quote("pattern1")
+ "(.*?)"
+ Pattern.quote("pattern2")
).matcher(str);
while(m.find()){
String match = m.group(1);
System.out.println(">"+match+"<");
//here you insert 'match' into the list
}
String str=“它是一个带有pattern1的字符串,在pattern1和pattern2之间有pattern1和pattern2,有时pattern1 pattern2没有”;
Matcher m=Pattern.compile(
模式。引用(“模式1”)
+ "(.*?)"
+模式。引用(“模式2”)
).matcher(str);
while(m.find()){
字符串匹配=m.group(1);
System.out.println(“>”+match+”你肯定想用匹配器来做这件事。@Amber“肯定”??考虑到代码中可能存在的内容,这是一种非常强大的语言。请参阅我的一行回答(不使用匹配器)
)@波希米亚人,看看我对你答案的评论。仅仅因为你可以使用某些东西并不意味着你应该使用。而且也非常难以理解。我不想在我必须维护的代码中看到这一点。真的吗?我一下子就编写了这一点。总之,只要在代码注释中添加我的解释,每个人都会很高兴,或者你可以使用匹配器来完成,不必使用注释来解释正在发生的事情,并且更好地支持未来对需求的潜在更改-例如,如果需要匹配多对不同的开始/结束标记,您的解决方案就会出现故障。使用匹配器也不需要构造中间字符串,中间字符串可能有一个如果操作的字符串很大,ant的性能会有很大的提高。@Justin谢谢。我以“代码越少越好”(注意保持可读性)的口头禅生活在我的生活中——它保持了“信噪比”"我很乐意在生产中使用这段代码。如果你熟悉正则表达式,它很容易理解,而且它使用API为你完成所有繁重的工作。我不明白为什么人们会投票选择另一个答案——它有大量的代码,只做这一行,而大量的代码会降低可读性!@ddmytrenko当然,只需在正则表达式中添加“忽略大小写”标志(?i)
:List strings=array.asList(input.replaceAll(^.*(?i)pattern1)”,“”)。split((?i)pattern2.*(?pattern1 |$);
谢谢!:)这非常有效!只需一件事,String textInBetween=m.group(1);//因为(.*)正在捕获组1
可能应该是匹配器。组(1)
但这只是一个小错误,测试代码运行得非常出色!@Justin:谢谢你发现了这个错误。我复制并粘贴了,但没有编辑所有内容。当新行字符位于起始词和结束词之间时,这不起作用。@Tajchert:只需将部分(.*)
更改为(?s)(.*)
,或将模式.DOTALL
标记添加到模式中。编译
。美丽干净的解决方案-感谢大家为我们所有人解决了这个问题。对于所有人,请确保您添加了Pattern.DOITALL,以便您可以捕获模式之间的多行文本。如果我希望模式1和模式2包含在输出中,该怎么办?@R11G您可以在输出中包含模式变量,或移动括号以包含模式:“(“+pattern.quote(pat1)+”*?“+pattern.quote(pat2)+”)并通过m.group(1)
获取它。
String pattern1 = "hgb";
String pattern2 = "|";
String text = "sdfjsdkhfkjsdf hgb sdjfkhsdkfsdf |sdfjksdhfjksd sdf sdkjfhsdkf | sdkjfh hgb sdkjfdshfks|";
Pattern p = Pattern.compile(Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2));
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group(1));
}
String str = "its a string with pattern1 aleatory pattern2 things between pattern1 and pattern2 and sometimes pattern1 pattern2 nothing";
Matcher m = Pattern.compile(
Pattern.quote("pattern1")
+ "(.*?)"
+ Pattern.quote("pattern2")
).matcher(str);
while(m.find()){
String match = m.group(1);
System.out.println(">"+match+"<");
//here you insert 'match' into the list
}
> aleatory <
> and <
> <