java - 在 Java 中的 String.replaceAll 上获取 java.lang.StackOverflowError
问题描述
我需要用“||”替换“OR”这个词 在给定的字符串中。只有当它在输入字符串中是一个完整的单词时才应该被替换。此外,如果它出现在引号内,则不应替换它。例如,如果输入字符串是
application.path="EXCEL.exe" OR application.path="EXCELSIOR.exe" OR application.path="XYZ OR ABC.exe"
输出应该是
application.path="EXCEL.exe" || application.path="EXCELSIOR.exe" || application.path="XYZ OR ABC.exe"
请注意,EXCELSIOR.exe 和“XYZ OR ABC.exe”中的 OR 不会被替换。
我使用的Java代码如下:
String inputStr = "(quote.AGE was 24 AND (application.path = \"**\\acad.exe\" OR application.path = \"**\\dxfdwg.exe\" OR application.path = \"**\\EXCELSIOR.EXE\" OR application.path = \"**\\iges.exe\" OR application.path = \"**\\notepad.exe\" OR application.path = \"**\\run_journal.exe\" OR application.path = \"**\\AcroRd32.exe\" OR application.path = \"**\\dllhost.exe\" OR application.path = \"**\\powerpnt.exe\" OR application.path = \"**\\Edge.exe\" OR application.path = \"**\\step203ug.exe\" OR application.path = \"**\\step214ug.exe\" OR application.path = \"**\\VisView.exe\" OR application.path = \"**\\Teamcenter.exe\" OR application.path = \"**\\ug_convert_part.exe\" OR application.path = \"**\\ugraf.exe\" OR application.path = \"**\\ugtopv.exe\" OR application.path = \"**\\wmplayer.exe\" OR application.path = \"**\\winword.exe\" OR application.path = \"**\\wordpad.exe\" OR application.path = \"**\\vlc.exe\" OR application.path = \"**\\dwgviewr.exe\" OR application.name = \"RMS\" OR application.path = \"**\\acrobat.exe\" OR application.path = \"**\\Alias.exe\" OR application.path = \"**\\awtessd.exe\" OR application.path = \"**\\proe.exe\" OR application.path = \"**\\STPViewer.exe\" OR application.path = \"**\\gom_inspect.exe\" OR application.path = \"**\\gom_cad_server2.exe\" OR application.path = \"**\\sldworks.exe\" OR application.path = \"**\\sldworks_fs.exe\" OR application.path = \"**\\sldProcMon.exe\" OR application.path = \"**\\AdapplicationMgr.exe\" OR application.path = \"**\\AdapplicationMgrSvc.exe\" OR application.path = \"**\\SE3Dtrans.exe\" OR application.path = \"**\\stamp.exe\" OR application.path = \"**\\psolid.exe\" OR application.path = \"**\\mpid.exe\" OR application.path = \"**\\mpirun.exe\" OR application.path = \"**\\FS.exe\" OR application.path = \"**\\xtop.exe\" OR application.path = \"**\\pro_comm_msg.exe\" OR application.path = \"**\\nmsd.exe\" OR application.path = \"**\\creoagent.exe\" OR application.path = \"**\\parametric.exe\" OR application.path = \"**\\PDFEditor.exe\" OR application.path = \"**\\CNEXT.exe\" OR application.path = \"**\\drafter.exe\" OR application.path = \"**\\convert.exe\" OR application.path = \"**\\ActCut3D.exe\" OR application.path = \"**\\ppcbasic.exe\" OR application.path = \"**\\deltamesh_stamping.exe\" OR application.path = \"Xasfsf\" OR application.path = \"sfdsdf\"))";
String replacedStr = inputStr.replaceAll("(?m)\\bOR\\b(?=(?:\"[^\"]*\"|[^\"])*$)", "||");
这适用于较短的字符串,但一旦长度超过 2000 个字符,就会引发以下错误:
java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:3796) 处 java.util.regex.Pattern$Branch.match(Pattern.java:4604) 处的线程“主”java.lang.StackOverflowError 中的异常java.util.regex.Pattern$GroupHead.match(Pattern.java:4658) 在 java.util.regex.Pattern$Loop.match(Pattern.java:4785) 在 java.util.regex.Pattern$GroupTail.match( Pattern.java:4717) 在 java.util.regex.Pattern$BranchConn.match(Pattern.java:4568) 在 java.util.regex.Pattern$CharProperty.match(Pattern.java:3777) 在 java.util.regex .Pattern$Branch.match(Pattern.java:4604)
我在其他一些线程(thread1,thread2)中读到 Java 不能很好地处理长字符串的正则表达式。有人可以建议我如何改进我的正则表达式以避免 StackOverflowError 吗?
解决方案
有人可以建议我如何改进我的正则表达式以避免 StackOverflowError 吗?
是的,我可以给你两个解决方案,你只需要从另一个角度看待你的问题。
这是对您的问题的快速分析和快速解决方案,您可以改用此正则表达式(.*?\"\s+)\bOR\b(\s+application.*?)
:
解决方案一
String inputStr = //that long String
String regex = "(.*?\"\\s+)\\bOR\\b(\\s+application.*?)";
String replacedStr = inputStr.replaceAll(regex, "$1||$2");
System.out.println(replacedStr);
我注意到您要替换的 OR 在"
ansspace
OR
之后存在application
,我的正则表达式将匹配该 OR 并替换它。
简短示例的输出,它将为您提供与长示例相同的结果:
application.path="EXCEL.exe" || application.path="EXCELSIOR.exe" || application.path="XYZ OR ABC.exe"
^^ ^^ ^^ ^^
解决方案二
如果您使用的是 Java 9+,则可以使用此正则表达式application.path=(\"(.*?)\")
来匹配所有内容,例如application.path="something here"
,收集结果||
String regex = "application.path=(\"(.*?)\")";
String text = Pattern.compile(regex)
.matcher(inputStr).results().map(MatchResult::group)
.collect(Collectors.joining(" || "));
推荐阅读
- ruby-on-rails - heroku 运行 rake db:seed 失败
- php - 数据库中的 PHP 下拉列表 - 如何按日期将选择限制为 8
- python - 如何在 tensorflow.js 上加载/重新训练/保存 ssd_inception_v2_coco?
- c - 尝试将整数写入 C 中的共享内存时出现分段错误(核心转储)
- python - 程序在数组中查找重复项并将它们放在 python 中唯一的后面?
- mysql - mysql bash命令在mobaextreme中失败,但n cmd windows成功
- python - 所选环境中没有 Pip 安装程序
- python - 帖子不显示
- c# - C#如何使用日期时间选择器选择过去的日期
- masstransit - 创建不同的消息或在 Masstransit 中进行某种过滤