获取包含与模式匹配的文本的对象列表

Get the list of object containing text matching a pattern

我目前正在使用 API Apache POI,我正在尝试用它编辑 Word 文档 (*.docx)。文档由段落组成(在 XWPFParagraph 个对象中),一个段落包含嵌入在 'runs' (XWPFRun) 中的文本。一个段落可以有很多 运行(取决于文本属性,但有时是随机的)。在我的文档中,我可以有特定的标签,我需要用数据替换它们(我所有的标签都遵循这种模式 <#TAG_NAME#>

例如,如果我处理包含文本 Some text with a tag <#SOMETAG#> 的段落,我可能会得到类似这样的结果

XWPFParagraph paragraph = ... // Get a paragraph from the document
System.out.println(paragraph.getText());
// Prints: Some text with a tag <#SOMETAG#>

但是如果我想编辑那个段落的文本我需要处理运行s并且运行s的数量是不固定的。因此,如果我使用该代码显示 运行s 的内容:

System.out.println("Number of runs: " + paragraph.getRuns().size());
for (XWPFRun run : paragraph.getRuns()) {
    System.out.println(run.text());
}

有时候可以这样:

// Output:
// Number of runs: 1
// Some text with a tag <#SOMETAG#>

其他时候也是这样

// Output:
// Number of runs: 4
// Some text with a tag 
// <#
// SOMETAG
// #>

我需要做的是获取包含标签开始的第一个 运行 和包含标签其余部分的后续 运行 的索引(如果标签被划分在许多 运行 中)。我已经设法获得了该算法的第一个版本,但它仅在标签的开头 (<#) 和标签的结尾 (#>) 不分开时才有效。 Here's what I've already done.

所以我想得到的是一个能够解决这个问题的算法,如果可能的话让它与任何给定的标签一起工作(不一定是 <##>,所以我可以用像这个 {{{ 和这个 }}}).

抱歉,如果我的英语不完美,请随时让我澄清您想要的任何一点。

最后我自己找到了答案,我完全改变了我对原始算法的思考方式(我对其进行了评论,以便它可以帮助可能与我处于相同情况的人)

// Before using the function, I'm sure that:
// paragraph.getText().contains(surroundedTag) == true
private void editParagraphWithData(XWPFParagraph paragraph, String surroundedTag, String replacement) {
    List<Integer> runsToRemove = new LinkedList<Integer>();
    StringBuilder tmpText = new StringBuilder();
    int runCursor = 0;

    // Processing (in normal order) the all runs until I found my surroundedTag
    while (!tmpText.toString().contains(surroundedTag)) {
        tmpText.append(paragraph.getRuns().get(runCursor).text());
        runsToRemove.add(runCursor);
        runCursor++;
    }

    tmpText = new StringBuilder();
    // Processing back (in reverse order) to only keep the runs I need to edit/remove
    while (!tmpText.toString().contains(surroundedTag)) {
        runCursor--;
        tmpText.insert(0, paragraph.getRuns().get(runCursor).text());
    }

    // Edit the first run of the tag
    XWPFRun runToEdit = paragraph.getRuns().get(runCursor);
    runToEdit.setText(tmpText.toString().replaceAll(surroundedTag, replacement), 0);

    // Forget the runs I don't to remove
    while (runCursor >= 0) {
        runsToRemove.remove(0);
        runCursor--;
    }

    // Remove the unused runs
    Collections.reverse(runsToRemove);
    for (Integer runToRemove : runsToRemove) {
        paragraph.removeRun(runToRemove);
    }
}

所以现在我正在处理该段落的所有运行,直到找到我包围的标签,然后我正在处理该段落以忽略第一运行,如果我不需要编辑它们的话。