【问题标题】:Java - splitting a file into sectionsJava - 将文件分成多个部分
【发布时间】:2019-01-28 18:38:34
【问题描述】:

我正在做一个项目以获取文件并保存其部分。 部分可以是

1.

2.

3.

等等,但也可以是

1.1

2.3.1.II.

等等

现在我知道如何阅读的基本知识了。我需要知道是否有一种很好的方法来检测文本并将其分成几部分。

我想过正则表达式,但我不知道足够的正则表达式来做到这一点。有什么建议吗?

更新

示例:

1. Position
1.1. Position.
1.2. Scope
1.3. Location. 
2. Compensation
2.1. Schedule
2.2. 
3. Term
3.1. Term.
3.1.i. bla
3.1.ii. bla bla

【问题讨论】:

  • 你能分享一些示例数据吗?和预期的输出?
  • 使用正则表达式似乎是一个不错的选择。也许如果您的部分行仅包含正则表达式,您可以通过测试正则表达式本身之后是否有某些内容来避免误报。 (例如 [your regex] vs [your regex] 其他)
  • 您的部分是否保证以数字开头?
  • @PushpeshKumarRajwanshi 添加示例
  • @Compass 是的,有保证

标签: java regex string file


【解决方案1】:

您可以使用此正则表达式来划分和捕获 group1 中的编号部分和 group2 中的段落部分。

^((?:[a-zA-Z\d]{1,2}\.)+)\s+(.*)

在这里,^((?:[a-zA-Z\d]{1,2}\.)+) 捕获编号部分,该部分以一到两个字母数字字符开头,后跟一个或多次完整的文字点。然后是一个空格,因此\s+ 然后(.*) 捕获假定为段落的剩余文本。使用您给定的示例数据,这就是我想出的。如果您需要更多不同的案例,请添加更多示例,我会给您进一步完善的解决方案。

Demo

这是一个示例 Java 代码,

List<String> list = Arrays.asList("1. Position", "1.1. Position.", "1.2. Scope", "1.3. Location. ",
        "2. Compensation", "2.1. Schedule", "2.2. ", "3. Term", "3.1. Term.", "3.1.i. bla", "3.1.ii. bla bla",
        "12.a. some para", "13.a. some para", "1.a. some para", "A.1.a. another para", "B.1.a. some para");
Pattern p = Pattern.compile("^((?:[a-zA-Z\\d]+\\.)+)\\s+(.*)");

list.stream().forEach(x -> {
    Matcher m = p.matcher(x);
    if (m.matches()) {
        System.out.println(x + " --> " + "number section: ("+m.group(1)+")" + " para section: ("+m.group(2)+")");
    }
});

打印,

1. Position --> number section: (1.) para section: (Position)
1.1. Position. --> number section: (1.1.) para section: (Position.)
1.2. Scope --> number section: (1.2.) para section: (Scope)
1.3. Location.  --> number section: (1.3.) para section: (Location. )
2. Compensation --> number section: (2.) para section: (Compensation)
2.1. Schedule --> number section: (2.1.) para section: (Schedule)
2.2.  --> number section: (2.2.) para section: ()
3. Term --> number section: (3.) para section: (Term)
3.1. Term. --> number section: (3.1.) para section: (Term.)
3.1.i. bla --> number section: (3.1.i.) para section: (bla)
3.1.ii. bla bla --> number section: (3.1.ii.) para section: (bla bla)
12.a. some para --> number section: (12.a.) para section: (some para)
13.a. some para --> number section: (13.a.) para section: (some para)
1.a. some para --> number section: (1.a.) para section: (some para)
A.1.a. another para --> number section: (A.1.a.) para section: (another para)
B.1.a. some para --> number section: (B.1.a.) para section: (some para)

【讨论】:

  • 这很好用,但也会产生一些阳性,例如以“发明”开头的行。
  • 如果您有这样的数据,那么我们可以将长度限制为 2 个字符(或者根据您的需要可能是 3 个),这样它就不会匹配更大的单词。让我更新我的帖子。
【解决方案2】:

您可以使用正则表达式匹配标题,例如这个(假设罗马数字是 u 到 X):

^((?:(?:\d+|I{1,3}|IV|VI{0,3}|IX|X)\.)+)

Demo

解释:

  • ^ 行首
  • \d+|I{1,3}|IV|VI{0,3}|IX|X - 匹配一个数字:

    • \d+ 位数
    • I{1,3}|IV|VI{0,3}|IX|X罗马数字
  • (?:...)非捕获组

  • \. 分隔数字的点
  • (...)+ 重复 NUMERAL DOT 组一次或多次

编辑:

在 java 中,您需要转义模式(以便 java 正确解释它)并使用 Pattern.MULTILINE(以便 ^ 标记行的开头而不是字符串的开头):

Pattern.compile("^((?:(?:\\d+|I{1,3}|IV|VI{0,3}|IX|X)\\.)+)", Pattern.MULTILINE)

【讨论】:

    猜你喜欢
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多