对多个区域使用 Matcher.appendReplacement()

2024-03-05

java Matcher.appendReplacement() 方法(带有appendTail())应该让我将源文本转换为结果文本,同时替换所有出现的模式。 伪语言的算法类似于:

while Matcher.find() {
  call Matcher.appendReplacement()
}
call Matcher.appendTail()

如果仅在给定区域内搜索模式,则一切都很好:

call Matcher.region()
while Matcher.find() {
  call Matcher.appendReplacement()
}
call Matcher.appendTail()

当在区域内匹配后,我想进一步移动该区域时,就会出现问题:

call Matcher.region()
while Matcher.find() {
  call Matcher.appendReplacement()
}
call Matcher.region()
while Matcher.find() {
  call Matcher.appendReplacement()
}
call Matcher.appendTail()

这不起作用,因为region()会重置匹配器,以便Matcher.appendReplacement()从文本的开头重新启动,导致结果包含源某些部分的重复。

正如 javadoc 所说,这是设计造成的。

替换可以位于多个区域内的模式的正确方法是什么?

编辑:添加了 java 示例,删除了文本示例

下面的 java 示例显示了来自类似的输入

狗1开始狗2a狗2b结束狗3开始狗4a狗4b结束狗5

你没有得到预期的输出

dog1开始cat2acat2b结束dog3开始cat4acat4b结束dog5

package test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestMatcher {

    public static void main(String[] args) throws Exception {
        String inputText = "dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5";
        System.out.println("input  = " + inputText);
        StringBuffer result = new StringBuffer();
        Pattern pattern = Pattern.compile("dog");
        Matcher matcher = pattern.matcher(inputText);

        int startPos = inputText.indexOf("start");
        int endPos = inputText.indexOf("end");
        System.out.println("Setting region to " + startPos + "," + endPos);
        matcher.region(startPos, endPos);
        while (matcher.find()) {
            matcher.appendReplacement(result, "cat");
        }
        System.out.println("Partial result = " + result);

        startPos = inputText.indexOf("start", endPos);
        endPos = inputText.indexOf("end", startPos);
        System.out.println("Setting region to " + startPos + "," + endPos);
        matcher.region(startPos, endPos);
        while (matcher.find()) {
            matcher.appendReplacement(result, "cat");
        }
        matcher.appendTail(result);
        System.out.println("Final result   = " + result);
    }
}

Output:

input  = dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5
Setting region to 5,23
Partial result = dog1 start cat2a cat
Setting region to 32,50
Final result   = dog1 start cat2a catdog1 start dog2a dog2b end dog3 start cat4a cat4b end dog5

子区域不是必须由单独的匹配器处理吗?喜欢:

public static void main(String[] args) {
  String inputText = "dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5";

  System.out.println("Input          = " + inputText);
  StringBuffer result = new StringBuffer();
  Pattern pattern = Pattern.compile("(start(.*?)end)");

  Matcher matcher = pattern.matcher(inputText);

  while (matcher.find()) {
    int s = matcher.start();
    int e = matcher.end();
    System.out.printf("(%d .. %d) -> \"%s\"\n", s, e, matcher.group(1));
    matcher.appendReplacement(result, processSubGroup(matcher.group(1), matcher.group(2)));
  }
  matcher.appendTail(result);
  System.out.println("Final result   = " + result);
}

static String processSubGroup(String subGroup, String contents) {
  StringBuffer result = new StringBuffer();
  Pattern pattern = Pattern.compile("dog");

  Matcher matcher = pattern.matcher(subGroup);

  while (matcher.find())
    matcher.appendReplacement(result, "cat");

  matcher.appendTail(result);
  return result.toString();
}

或者,没有日志相关的东西并且更简单:

public static void main(String[] args) {
  String inputText = "dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5";

  StringBuffer result = new StringBuffer();
  Pattern pattern = Pattern.compile("(start(.*?)end)");

  Matcher matcher = pattern.matcher(inputText);

  while (matcher.find())
    matcher.appendReplacement(result, processSubGroup(matcher.group(1), matcher.group(2)));

  matcher.appendTail(result);
  System.out.println("Final result   = " + result);
}

static String processSubGroup(String subGroup, String contents) {
  return Pattern.compile("dog").matcher(subGroup).replaceAll("cat");
}

Result:

Input          = dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5
(5 .. 26) -> "start dog2a dog2b end"
(32 .. 53) -> "start dog4a dog4b end"
Final result   = dog1 start cat2a cat2b end dog3 start cat4a cat4b end dog5

或者更抽象的方法:

interface GroupProcessor {
  String process(String group);
}

public static void main(String[] args) {
  String inputText = "dog1 dogs dog2a dog2b enddogs cow1 dog3 cows cow2a cow2b endcows dog4 dogs dog5a dog5b enddogs cow3";

  String result = inputText;

  result = processGroup(result, "dogs*enddogs", (group) -> {
    return Pattern.compile("dog").matcher(group).replaceAll("cat");
  });

  result = processGroup(result, "cows*endcows", (group) -> {
    return Pattern.compile("cow").matcher(group).replaceAll("sheep");
  });

  System.out.println("Input        = " + inputText);
  System.out.println("Final result = " + result);
}

static String processGroup(String input, String regex, GroupProcessor processor) {
  StringBuffer result = new StringBuffer();
  Pattern pattern = Pattern.compile(String.format("(%s)", regex.replace("*", "(.*?)")));

  Matcher matcher = pattern.matcher(input);

  while (matcher.find())
    matcher.appendReplacement(result, processor.process(matcher.group(1)));

  matcher.appendTail(result);
  return result.toString();
}

这将为我们提供:

Input        = dog1 dogs dog2a dog2b enddogs cow1 dog3 cows cow2a cow2b endcows dog4 dogs dog5a dog5b enddogs cow3
Final result = dog1 cats cat2a cat2b endcats cow1 dog3 sheeps sheep2a sheep2b endsheeps dog4 cats cat5a cat5b endcats cow3

Upd.

原因,为什么Matcher.region()重置隐式匹配器状态,因此,lastAppendPosition.

appendReplacement and appendTail在某种程度上是一种只向前移动的机制,而.region()并不是那么确定。

假设以下情况:对于 100 个字符的字符串,您应用了区域 0..20,执行find()-appendReplacement()循环,然后将区域移动到例如 30..60,并再次执行替换循环。

现在你有 0..100 源字符串和 0..60 替换结果字符串StringBuffer.

接下来,将区域 10..40 应用到源字符串...接下来做什么?如果源字符串的该区域不包含匹配项 - 好的,什么都不做,但如果它does包含匹配项?应该在哪里appendReplacement追加/插入替换结果?结果字符串已经超过了 10..40 区域并且appendReplacement only appends, not replaces输出缓冲区中字符串的分区。

如果存在某种约束机制,则该区域设置仅限于类似MAX(start, lastAppendPosition)..MIN(end, sourceLength),那么好吧,附加机制可以正常工作,但是.region()方法没有这样的限制,或者它们(限制)会使.region()方法对于搜索来说毫无用处(其中is主要目的.region()方法)。

这就是为什么.region()重置匹配器的隐式状态,使其与appendReplacement()相关的东西。如果您需要不同的行为 - 扩展Matcher通过封装的类。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对多个区域使用 Matcher.appendReplacement() 的相关文章

  • 如何克服原语按值传递的事实

    我有一段很长的代码来计算两个值 doubles 对我来说 我在几个地方使用了这段代码 为了坚持 DRY 原则 我应该将这段代码重构为一个很好的单元测试方法 但是我不能让它返回两个双精度数 而双精度数是原始的 因此不能按值传递和操作 我能想到
  • Java中字符串中特殊字符的替换

    Java中如何替换字符串 E g String a adf sdf 如何替换和避免特殊字符 您可以删除除此之外的所有字符可打印的 ASCII 范围 http en wikipedia org wiki ASCII ASCII printab
  • 在文本文件中写入多行(java)

    下面的代码是运行命令cmd并使用命令行的输出生成一个文本文件 下面的代码在 Eclipse 的输出窗口中显示了正确的信息 但在文本文件中只打印了最后一行 谁能帮我这个 import java io public class TextFile
  • 如何创建一个显示 Spinners 的 x 和 y 值的表格?

    我想创建一个位于图表右侧的表格 其中显示 2 列 x 和 y 值已输入到xSpin and ySpin旋转器 我已经画了一张我想要桌子放置的位置的图 我尝试过在网格窗格布局中使用文本框来创建表格并将值直接输入到文本框网格中 但是我无法将它们
  • Java:如何从转义的 URL 获取文件?

    我收到了一个定位本地文件的 URL 事实上我收到的 URL 不在我的控制范围内 URL 按照 RFC2396 中的定义进行有效转义 如何将其转换为 Java File 对象 有趣的是 URL getFile 方法返回一个字符串 而不是文件
  • 正则表达式拆分数字和字母组,不带空格

    如果我有一个像 11E12C108N 这样的字符串 它是字母组和数字组的串联 如何在中间没有分隔符空格字符的情况下分割它们 例如 我希望分割结果为 tokens 0 11 tokens 1 E tokens 2 12 tokens 3 C
  • 如何在不超过最大值的情况下增加变量?

    我正在为学校开发一个简单的视频游戏程序 我创建了一个方法 如果调用该方法 玩家将获得 15 点生命值 我必须将生命值保持在最大值 100 并且由于我目前的编程能力有限 我正在做这样的事情 public void getHealed if h
  • Hibernate.createBlob() 方法从 Hibernate 4.0.1 开始已弃用,并移至 Hibernate.getLobCreator(Session session).createBlob()

    Method Hibernate createBlob 已弃用自休眠4 0 1并搬到Hibernate getLobCreator Session session createBlob 任何解决方案我应该在方法内传递什么getLobCrea
  • 使用 AES SecretKey 的 Java KeyStore setEntry()

    我目前正在 Java 中开发一个密钥处理类 特别是使用 KeyStore 我正在尝试使用 AES 实例生成 SecretKey 然后使用 setEntry 方法将其放入 KeyStore 中 我已经包含了代码的相关部分 The KS Obj
  • Java 文件上传速度非常慢

    我构建了一个小型服务 它从 Android 设备接收图像并将其保存到 Amazon S3 存储桶中 代码非常简单 但是速度非常慢 事情是这样的 public synchronized static Response postCommentP
  • 如何使用 Maven 打包并运行具有依赖项的简单命令行应用程序?

    我对 java 和 Maven 都是全新的 所以这可能非常简单 如果我遵循maven2hello world此处的说明 http maven apache org guides getting started maven in Five m
  • 使用 SQLITE 按最近的纬度和经度坐标排序

    我必须获得一个 SQLite SQL 语句 以便在给定初始位置的情况下按最近的纬度和经度坐标进行排序 这是我在 sqlite 数据库中的表的例句 SELECT id name lat lng FROM items EXAMPLE RESUL
  • Java 中的“Lambdifying”scala 函数

    使用Java和Apache Spark 已用Scala重写 面对旧的API方法 org apache spark rdd JdbcRDD构造函数 其参数为 AbstractFunction1 abstract class AbstractF
  • IntelliJ - 调试模式 - 在程序内存中搜索文本

    我正在与无证的第三方库合作 我知道有一定的String存储在库深处的某个字段中的某处 我可以预测的动态值 但我想从库的 API 中获取它 有没有一种方法可以通过以下方式进行搜索 类似于全文搜索 full程序内存处于调试模式并在某个断点处停止
  • 如何知道抛出了哪个异常

    我正在对我们的代码库进行审查 有很多这样的陈述 try doSomething catch Exception e 但我想要一种方法来知道 doSomething 抛出了哪个异常 在 doSomething 的实现中没有 throw 语句
  • 在 Spring 中重构这个的最佳方法?

    private final ExecutorService executorParsers Executors newFixedThreadPool 10 public void parse List
  • Java中的Object类是什么?

    什么是或什么类型private Object obj Object http download oracle com javase 6 docs api java lang Object html是Java继承层次结构中每个类的最终祖先 从
  • 具有特定参数的 Spring AOP 切入点

    我需要创建一个我觉得很难描述的方面 所以让我指出一下想法 com x y 包 或任何子包 中的任何方法 一个方法参数是接口 javax portlet PortletRequest 的实现 该方法中可能有更多参数 它们可以是任何顺序 我需要
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • 如何从 Maven 存储库引用本机 DLL?

    如果 JAR 附带 Maven 存储库中的本机 DLL 我需要在 pom xml 中放入什么才能将该 DLL 放入打包中 更具体地举个例子Jacob http search maven org artifactdetails 7Cnet s

随机推荐

  • 基于 R 中字符串比较的相似度分数(编辑距离)

    我正在尝试根据两个字符串之间的比较来分配相似度分数 R 中是否有相同的函数 我知道 SAS 中有一个名为 SPEDIS 的函数 如果R中有这样的函数 请告诉我 功能adist http stat ethz ch R manual R pat
  • 将 Data.Constraint.Forall 与等式约束一起使用

    假设我有一个这样的函数 LANGUAGE ScopedTypeVariables class C a where foo forall f a b C f a C f b gt f a gt f b foo 现在 如果我想移动范围a and
  • 用于 Web 服务的 SOAP 还是 REST? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 REST 是一种更好的 Web 服务方法还是 SOAP 或者它们是针对不同问题的不同工具吗 或者这是一个微妙的问题 也就是说 一个在某些领域比另
  • Appfabric WF4-WCF服务,如何在没有httpcontext的情况下检索codeactivity中的当前url?

    我开发了一个带有代码活动的 wf wcf 服务 我想在其中检索该服务的当前 URL 如果我禁用 appfabric 的持久性功能 我可以使用以下命令检索 URL HttpContext Current Request Url ToStrin
  • Swift - 协议作为按钮操作的目标类型

    我正在尝试创建 HeaderView 它是 UIView 的子类 它包含一个关闭按钮和一个标题标签 class HeaderView UIView private var titleLabel UILabel private var clo
  • 无法将 _InternalLinkedHashMap 转换为任何内容

    尽管我首先将其作为地图上传 但从 Firebase RealtimeDatabase 获取数据作为地图时遇到了一些问题 我看到的所有解决方案都是您应该将 snapshot value 转换为传入的数据类型 但对我来说没有任何迭代 我已经可以
  • 如何将 MongoDB 与 Solr 集成?

    我以前见过这个问题 但从未收到真正的答案 所以我想知道 有人可以指出我如何将 mongoDB 与 Solr 集成的正确方向吗 我正在寻找伪实时和最终的一致性 做过这件事的人可以透露一些信息吗 如果有帮助的话 我还将 PHP Zend 与 D
  • 如何使用 Rails 2.1 和 MySQL 定义 BigInt 主键?

    从 Rails 2 1 开始 如果您在迁移中定义一个新列 其类型设置为 integer 且 limit 设置为 5 或更多 则在 MySQL 数据库中实际创建的列将是 BigInt 类型 那很完美 但我不知道如何创建具有 BigInt 主键
  • 高级错误处理

    我最近摆了个姿势这个问题 https stackoverflow com questions 15295004 disregarding simple warnings errors in trycatch noredirect 1 com
  • 使用 Java 为 Blogger API 验证自己的 Google 帐户

    我想编写一个将本地文件发布到 Google Blogger 的机器人 我将是唯一使用此应用程序的人 因此我不需要设置用户友好的身份验证例程 我花了一个晚上尝试进行设置 但仍然在处理 OAuth 请求方面遇到困难 我创建了一个新的 Googl
  • 现代 OpenGL 相当于 glBegin/glEnd 的是什么

    我正在为 OpenGL 构建一个图形 API 它基于基本的调用绘制图形样式 基本上 不是将数据存储到 GPU 中 并使用它的句柄调用它 而是提供信息来绘制每次更新应该绘制的内容 我知道它很慢 但它很简单 而且适用于非性能关键型应用程序 无论
  • 正则表达式:如何匹配不仅仅是数字的字符串

    是否可以编写一个正则表达式来匹配所有不匹配的字符串only包含数字 如果我们有这些字符串 abc a4c 4bc ab4 123 它应该匹配第一个 但不是最后一个 我尝试在 RegexBuddy 中摆弄前瞻之类的东西 但我似乎无法弄清楚 d
  • 如何在关系数据库中建模多语言实体

    如果我们要开发一个多语言应用程序 我们应该将翻译存储在资源文件 or the database 假设我们选择在数据库中进行 是否有一种标准方法来建模多语言实体关系模型 1 一张大翻译表 我们可以将所有翻译存储在一张表中并使用语言中立键为属性
  • Flexbox行:不根据内容增长? [复制]

    这个问题在这里已经有答案了 我有以下结构 我想了解为什么我的行不随其内部内容增长 row border solid red display flex flex direction row cell border solid green fl
  • 在 Maps API 浏览器上设置 HTTP Referrer 会导致 403 错误

    我对 HTTP Referrer 设置如何在 Google Maps API 浏览器密钥上工作感到困惑 我正在构建一个网页 以编程方式从 Google 地图请求图像 主要是 Google 地图街景图像 API 但也从 Javascript
  • spring-boot-starter-web 和 spring-boot-starter-webflux 不能一起工作吗?

    当我开始学习spring webflux 我对这个组件有疑问 我建立了一个简单的项目 使用maven来管理它 我添加了相关的依赖项spring boot starter web and spring boot starter webflux
  • Rufus 调度程序未登录生产环境

    我的 Rails 应用程序在初始化程序中使用 rufus scheduler 启动一个进程 这是初始化程序代码的精简版本 config logger isn t available here so we have to grab it fr
  • React 将 JQuery 代码应用于组件内的元素

    我有一个正在使用 React 的应用程序 我现在遇到一个问题 我正在尝试实施bootstrap 所见即所得 bootstrap3 所见即所得 https github com bootstrap wysiwyg bootstrap3 wys
  • 自动删除SQS队列

    有没有办法完全自动删除 SQS 队列 我有一个解决方案 其中服务器在启动时创建 SQS 并订阅 SNS 主题 然而 可能存在服务器崩溃且无法恢复的情况 在这种情况下 我会用另一台服务器替换该服务器 该服务器会在启动时创建自己的队列 现在之前
  • 对多个区域使用 Matcher.appendReplacement()

    java Matcher appendReplacement 方法 带有appendTail 应该让我将源文本转换为结果文本 同时替换所有出现的模式 伪语言的算法类似于 while Matcher find call Matcher app