Java RegEx - 正则表达式用开始和结束分割段落

Posted

技术标签:

【中文标题】Java RegEx - 正则表达式用开始和结束分割段落【英文标题】:Java RegEx - Regular expression to split a paragraph with start and end 【发布时间】:2009-11-10 09:54:12 【问题描述】:

我是 Java 正则表达式的新手。请帮助我。 考虑以下段落,

段落:

            Name abc
            sadghsagh
            hsajdjah Name
            ggggggggg
            !!!
            Name ggg
            dfdfddfdf Name
            !!!
            Name hhhh
            sahdgashdg Name
            asjdhjasdh
            sadasldkalskd
            asdjhakjsdhja
            !!!

我需要将以上段落拆分为以 Name 开头并以 !!! 结尾的文本块.这里我不想用!!!作为分割段落的唯一分隔符。我还需要在我的正则表达式中包含起始序列(名称)。

ie.,我的结果 api 应该看起来像 SplitAsBlocks("Paragraph","startswith Name","endswith !!!”)

如何实现这一点,请任何人帮助我......

现在我想要与 Brito 相同的输出......但是在这里我在“hsajdjah”之后添加了名称。这里将文本拆分为以下内容:

Name
ggggggggg
!!!

但我需要

Name abc
sadghsagh
hsajdjah Name
ggggggggg
!!!

也就是说,我必须匹配位于行首而不是中间的名称。

请给我建议...

Bart ...请参阅下面的输入案例以了解您的代码...

我需要使用带有参数 start => Name 和 end => 的 API 拆分以下内容! 但输出各不相同..我只有 3 个块以 Name 开头并以 ! . 我也附上了输出。

String myInput =    "Name hhhhh class0"+ "\n"+
                     "HHHHHHHHHHHHHHHHHH"+ "\n"+
                     "!"+ "\n"+
                     "Name TTTTT TTTT"+ "\n"+
                     "GGGGGG UUUUU IIII"+ "\n"+
                     "!"+ "\n"+
                     "Name JJJJJ WWWW"+ "\n"+
                     "IIIIIIIIIIIIIIIIIIIII"+ "\n"+
                     "!"+ "\n"+
                     "RRRRRRRRRRR TTTTTTTT"+ "\n"+
                     "HHHHHH"+ "\n"+
                     "JJJJJ 1 Name class1"+ "\n"+
                     "LLLLL 5 Name class5"+ "\n"+
                     "!"+ "\n"+
                     "OOOOOO HHHH FFFFFF"+ "\n"+
                     "service 0 Name class12"+ "\n"+
                     "!"+ "\n"+
                     "JJJJJ YYYYYY 3/0"+ "\n"+
                     "KKKKKKK"+ "\n"+
                     "UUU UUU UUUUU"+ "\n"+
                     "QQQQQQQ"+ "\n"+
                         "!";
    String[] tokens = tokenize(myInput, "Name", "!");
    int n = 0;
    for(String t : tokens) 
        System.out.println("---------------------------\n"+(++n)+"\n"+t);
    

输出:

---------------------------
1
Name hhhhh class0
HHHHHHHHHHHHHHHHHH
!
---------------------------
2
Name TTTTT TTTT
GGGGGG UUUUU IIII
!
---------------------------
3
Name JJJJJ WWWW
IIIIIIIIIIIIIIIIIIIII
!
---------------------------
4
Name class1
LLLLL 5 Name class5
!
---------------------------
5
Name class12
!

在这里我只需要在行首而不是中间的名称... 如何为此添加正则表达式...

【问题讨论】:

代码块请使用四个空格缩进。 ??? Name abc sadghsagh hsajdjah Name ggggggggg !!! 正是您尝试我的建议时所得到的。你有没有尝试过我的建议?我在演示中调整了输入,当你运行它时,你会看到它产生了你刚才描述的输出。 是的,巴特我试过你的建议,它工作正常,但在特定情况下失败..我在上面的代码中添加了特定的输入情况..请看... 请注意邮件格式。 不客气unknown。你明白尽可能清楚地表达自己是多么重要吗?在此处(或公共论坛上的任何地方)提交下一个问题之前,请校对您的问题,看看您是否可以预览您的消息发布后将如何结束:格式也很重要。祝你好运。 【参考方案1】:

试试:

import java.util.*;
import java.util.regex.*;

public class Main  

    public static String[] tokenize(String text, String start, String end) 
        // old line:
        //Pattern p = Pattern.compile("(?s)"+Pattern.quote(start)+".*?"+Pattern.quote(end));
        // new line:
        Pattern p = Pattern.compile("(?sm)^"+Pattern.quote(start)+".*?"+Pattern.quote(end)+"$");

        Matcher m = p.matcher(text);
        List<String> tokens = new ArrayList<String>();
        while(m.find()) 
            tokens.add(m.group());
        
        return tokens.toArray(new String[]);
    

    public static void main(String[] args) 
        String text = "Name abc" + "\n" +
            "sadghsagh"          + "\n" +
            "hsajdjah Name"      + "\n" +
            "ggggggggg"          + "\n" +
            "!!!"                + "\n" +
            "Name ggg"           + "\n" +
            "dfdfddfdf Name"     + "\n" +
            "!!!"                + "\n" +
            "Name hhhh"          + "\n" +
            "sahdgashdg Name"    + "\n" +
            "asjdhjasdh"         + "\n" +
            "sadasldkalskd"      + "\n" +
            "asdjhakjsdhja"      + "\n" +
            "!!!";
        String[] tokens = tokenize(text, "Name", "!!!");
        int n = 0;
        for(String t : tokens) 
            System.out.println("---------------------------\n"+(++n)+"\n"+t);
        
    

【讨论】:

谢谢 Bart .. 我需要姓名和 !!!在我的最后一个字符串中。另外我的条件是同时使用 Name 和 !!!拆分字符串不使用 Name 或 !!! . @Kobi:不,在 Java 中,您不会在正则表达式周围使用分隔符。在这件事上不要把 Java 和 javascript 混为一谈! Bart 非常感谢您的关注...您将文本定义为单行如下... String text = "Name abc sadghsagh hsajdjah !!! Name ggg dfdfddfdf !!! Name hhhh sahdgashdg asjdhjasdh sadasldkalskd asdjhakjsdhja !!!";但在我的情况下,每个单词都在一个单独的行中..请建议我如何分割这种类型的段落? 您的意思是:return tokens.toArray(new String[tokens.size()]) @Bart - 抱歉,Java 当然不支持。我很困惑,确定这是 JavaScript。抱歉,不知道怎么回事……【参考方案2】:
String s = "Name abc sadghsagh hsajdjah !!! Name ggg dfdfddfdf !!! Name hhhh sahdgashdg asjdhjasdh sadasldkalskd asdjhakjsdhja !!!!! ";
String startsWith = "Name";
String endsWith = "!!!";

// non-greedily get all groups starting with Name and ending with !!!
String pattern = String.format("(%s).*?(%s)", Pattern.quote(startsWith), Pattern.quote(endsWith));
System.out.println(pattern);

Matcher m = Pattern.compile(pattern, Pattern.DOTALL).matcher(s);
while (m.find()) 
  System.out.println(m.group());

输出:

(\QName\E).*?(\Q!!!\E)
Name abc sadghsagh hsajdjah !!!
Name ggg dfdfddfdf !!!
Name hhhh sahdgashdg asjdhjasdh sadasldkalskd asdjhakjsdhja !!!

【讨论】:

请注意,默认情况下,DOT 不匹配换行符。此外,如果 OP 想要“拆分”的子字符串包含正则表达式元字符,事情就会出错。最后,group()group(0) 相同,但这只是吸引眼球。 感谢 Sfussenegger .... 如果 String s 是单行,则上述解决方案可以正常工作...但在我的情况下,它是一个段落,即,每个单词之后都有一个换行符.. .请如何拆分这个..帮助我.. 您可以添加标记 s(单行模式)以使换行符与 Dotall 运算符 (.) 匹配,相关行将是 Matcher m = Pattern.compile(pattern, Pattern.DOTALL ).matcher(s); 特殊字符应该不是问题,因为我建议使用处理特殊字符的Pattern.quote(startsWith)。此外,我编辑了我的代码以使用 group()Pattern.DOTALL 在您编辑答案之前,我发布了有关特殊字符的评论。您的第一个答案不包含Pattern.quote(...)'s。【参考方案3】:

如果您想在结果中同时保留Name!!!,也应该执行以下操作。

String[] 部分 = string.split("(?=(Name|!!!))");

编辑:这是更正的版本:

String[] parts = string.split("(?<=!!!)\\s*(?=Name)");

这将在!!!Name 之间的任何空白处拆分,仅此而已;特此保留这两个部分。如果您不想在 !!!Name 上拆分,请将 \\s* 替换为 \\s+ 以允许一对多匹配而不是零对多匹配。

Edit2:附上输入/输出的例子。输入是从 topicstart 复制的:

String string = "Name hhhhh class0" + "\n" + "HHHHHHHHHHHHHHHHHH" + "\n" + "!" + "\n"
    + "Name TTTTT TTTT" + "\n" + "GGGGGG UUUUU IIII" + "\n" + "!" + "\n"
    + "Name JJJJJ WWWW" + "\n" + "IIIIIIIIIIIIIIIIIIIII" + "\n" + "!" + "\n"
    + "RRRRRRRRRRR TTTTTTTT" + "\n" + "HHHHHH" + "\n" + "JJJJJ 1 Name class1" + "\n"
    + "LLLLL 5 Name class5" + "\n" + "!" + "\n" + "OOOOOO HHHH FFFFFF" + "\n"
    + "service 0 Name class12" + "\n" + "!" + "\n" + "JJJJJ YYYYYY 3/0" + "\n" + "KKKKKKK"
    + "\n" + "UUU UUU UUUUU" + "\n" + "QQQQQQQ" + "\n" + "!";

String[] parts = string.split("(?<=!)\\s*(?=Name)");
for (String part : parts) 
    System.out.println(part);
    System.out.println("---------------------------------");

输出:

Name hhhhh class0
HHHHHHHHHHHHHHHHHH
!
---------------------------------
Name TTTTT TTTT
GGGGGG UUUUU IIII
!
---------------------------------
Name JJJJJ WWWW
IIIIIIIIIIIIIIIIIIIII
!
RRRRRRRRRRR TTTTTTTT
HHHHHH
JJJJJ 1 Name class1
LLLLL 5 Name class5
!
OOOOOO HHHH FFFFFF
service 0 Name class12
!
JJJJJ YYYYYY 3/0
KKKKKKK
UUU UUU UUUUU
QQQQQQQ
!
---------------------------------

看起来不错?

【讨论】:

嗨 BalusC,你在这里使用或条件...但我需要使用和条件... 对不起,我错过了这个关键点。我会尽快更新答案。 谢谢BalusC,我已经测试了你的技巧,但是在这里请用我在我的问题中解释的上述输入测试你的代码。这里的输出不同..请看.. 是的,但是看到上面的第三个输出在我的情况下是错误的......即,我需要打破第一个!标记自己,但在上述情况下,它会显示所有行到最后...请执行 Bart 的代码并与您的输出进行比较...谢谢 BalusC 所以 .. 即使文本可能包含“!”,例如“class!0”,代码仍然应该中断吗?这对我来说似乎不合逻辑。你会更清楚地指定要求。 IE。做“!”总是在换行之前?等等。你必须考虑到一切。

以上是关于Java RegEx - 正则表达式用开始和结束分割段落的主要内容,如果未能解决你的问题,请参考以下文章

java正则中REGEX = "[\u4e00-\u9fa5]+"是啥意思

用Java正则表达式来过滤Excle格式。比如Excle文件格式有.xlsx”和.xls两种。那么正则表达式怎么写呢。

regex正则

std::regex,匹配字符串的开始/结束

Regex 正则表达式中几个符号([ ] ^ ?: ?= ?!)的概念

JAVA正则表达式