Java 正则表达式匹配多行部分和小节
Java regex to match multiline sections with subsections
作为更简单的 Whosebug
question 的扩展,是否有一个 Java
正则表达式可以一次从多行文本文档中提取每个部分和小节,具有结构喜欢
<Irrelevant line>
...
<Irrelevant line>
####<section_title>
OVERVIEW
...
...
INTRODUCTION
...
...
DETAILS
...
...
####<section_title>
OVERVIEW
...
...
INTRODUCTION
...
...
DETAILS
...
...
section_title
可以是任何内容,它以及每个小节标题(概述、简介、详细信息)是该行中唯一的文本。所有其他行可以在多行中包含从空到数千个字符的任何文本。
或者,当然,可以使用 BufferedReader
处理文档并逐行阅读,但正则表达式会提供更优雅的解决方案。
以下正则表达式在迭代时将 return 一次 sub-section,可选择包括第一个 sub-section.
部分 header
(?m)(?:^####(.*)\R)?^(OVERVIEW|INTRODUCTION|DETAILS)\R(?s:(.*?))(?=^####|^(?:OVERVIEW|INTRODUCTION|DETAILS)$|\z)
(?m)
表示 ^
和 $
匹配正则表达式其余部分的行首和行尾(分别),因此我们使用 \z
来匹配输入结束,这是 $
通常匹配的内容。
(?s:XXX)
使 .
匹配 任何 具有 XXX
模式的字符,包括行分隔符(\r
、\n
).
\R
匹配 \r
、\n
或 \r\n
,即不管 OS(Windows 与Linux).
使用 .*?
(不情愿)匹配后接 (?=XXX)
将使正则表达式匹配文本,但不包括 XXX
模式。
演示
(在 regex101.com 上也可用)
String regex = "(?m)(?:^####(.*)\R)?^(OVERVIEW|INTRODUCTION|DETAILS)\R(?s:(.*?))(?=^####|^(?:OVERVIEW|INTRODUCTION|DETAILS)$|\z)";
String input = "<Irrelevant line>\r\n" +
"...\r\n" +
"<Irrelevant line>\r\n" +
"####<section_title>\r\n" +
"OVERVIEW\r\n" +
"...\r\n" +
"...\r\n" +
"INTRODUCTION\r\n" +
"...\r\n" +
"...\r\n" +
"DETAILS\r\n" +
"...\r\n" +
"...\r\n" +
"####<section_title>\r\n" +
"OVERVIEW\r\n" +
"...\r\n" +
"...\r\n" +
"INTRODUCTION\r\n" +
"...\r\n" +
"...\r\n" +
"DETAILS\r\n" +
"...\r\n" +
"...";
for (Matcher m = Pattern.compile(regex).matcher(input); m.find(); ) {
String sectionTitle = m.group(1);
String subSectionTitle = m.group(2);
String content = m.group(3);
if (sectionTitle != null)
System.out.println("sectionTitle: " + sectionTitle);
System.out.println("subSectionTitle: " + subSectionTitle);
System.out.println("content: " + content.replaceAll("(?ms)(?<=.)^", " "));
}
输出
sectionTitle: <section_title>
subSectionTitle: OVERVIEW
content: ...
...
subSectionTitle: INTRODUCTION
content: ...
...
subSectionTitle: DETAILS
content: ...
...
sectionTitle: <section_title>
subSectionTitle: OVERVIEW
content: ...
...
subSectionTitle: INTRODUCTION
content: ...
...
subSectionTitle: DETAILS
content: ...
...
作为更简单的 Whosebug
question 的扩展,是否有一个 Java
正则表达式可以一次从多行文本文档中提取每个部分和小节,具有结构喜欢
<Irrelevant line>
...
<Irrelevant line>
####<section_title>
OVERVIEW
...
...
INTRODUCTION
...
...
DETAILS
...
...
####<section_title>
OVERVIEW
...
...
INTRODUCTION
...
...
DETAILS
...
...
section_title
可以是任何内容,它以及每个小节标题(概述、简介、详细信息)是该行中唯一的文本。所有其他行可以在多行中包含从空到数千个字符的任何文本。
或者,当然,可以使用 BufferedReader
处理文档并逐行阅读,但正则表达式会提供更优雅的解决方案。
以下正则表达式在迭代时将 return 一次 sub-section,可选择包括第一个 sub-section.
部分 header(?m)(?:^####(.*)\R)?^(OVERVIEW|INTRODUCTION|DETAILS)\R(?s:(.*?))(?=^####|^(?:OVERVIEW|INTRODUCTION|DETAILS)$|\z)
(?m)
表示 ^
和 $
匹配正则表达式其余部分的行首和行尾(分别),因此我们使用 \z
来匹配输入结束,这是 $
通常匹配的内容。
(?s:XXX)
使 .
匹配 任何 具有 XXX
模式的字符,包括行分隔符(\r
、\n
).
\R
匹配 \r
、\n
或 \r\n
,即不管 OS(Windows 与Linux).
使用 .*?
(不情愿)匹配后接 (?=XXX)
将使正则表达式匹配文本,但不包括 XXX
模式。
演示
(在 regex101.com 上也可用)
String regex = "(?m)(?:^####(.*)\R)?^(OVERVIEW|INTRODUCTION|DETAILS)\R(?s:(.*?))(?=^####|^(?:OVERVIEW|INTRODUCTION|DETAILS)$|\z)";
String input = "<Irrelevant line>\r\n" +
"...\r\n" +
"<Irrelevant line>\r\n" +
"####<section_title>\r\n" +
"OVERVIEW\r\n" +
"...\r\n" +
"...\r\n" +
"INTRODUCTION\r\n" +
"...\r\n" +
"...\r\n" +
"DETAILS\r\n" +
"...\r\n" +
"...\r\n" +
"####<section_title>\r\n" +
"OVERVIEW\r\n" +
"...\r\n" +
"...\r\n" +
"INTRODUCTION\r\n" +
"...\r\n" +
"...\r\n" +
"DETAILS\r\n" +
"...\r\n" +
"...";
for (Matcher m = Pattern.compile(regex).matcher(input); m.find(); ) {
String sectionTitle = m.group(1);
String subSectionTitle = m.group(2);
String content = m.group(3);
if (sectionTitle != null)
System.out.println("sectionTitle: " + sectionTitle);
System.out.println("subSectionTitle: " + subSectionTitle);
System.out.println("content: " + content.replaceAll("(?ms)(?<=.)^", " "));
}
输出
sectionTitle: <section_title>
subSectionTitle: OVERVIEW
content: ...
...
subSectionTitle: INTRODUCTION
content: ...
...
subSectionTitle: DETAILS
content: ...
...
sectionTitle: <section_title>
subSectionTitle: OVERVIEW
content: ...
...
subSectionTitle: INTRODUCTION
content: ...
...
subSectionTitle: DETAILS
content: ...
...