【问题标题】:Regex which satisfies 3 separate cases满足 3 种不同情况的正则表达式
【发布时间】:2017-09-25 18:55:15
【问题描述】:

我正在尝试找出一个可以与 java 的 String.split(regex) 一起使用的正则表达式,以便从文件中获取“行”数组。

回车不定义行尾,而是逗号定义 - 但不是所有逗号。如果逗号位于括号、单引号或注释之间(/* 注释,更多注释 */),则不表示一行结束。

例子:

1 test fixed(5,2),
  2 another_test char(12),
  2 a_third_test,
    3 one pic'9{9}V.99',
    3 two pic'9,999V.99',
    3 three fixed(7,2),
  /* test,t*/
  /*test 2,*/
  /*and more */
  2 another_field fixed bin(13),
  2 a_really_long_super_long_field_name_requiring_two_lines_for_declaration
    char(1),
  2 a_field char(8);

预期的输出是(为清楚起见省略了 \t 和额外的空格):

1 test fixed(5,2)
2 another_test char(12)
2 a_third_test
3 one pic'9{9}V.99'
3 two pic'9,999V.99'
3 three fixed(7,2)
/* test,t*//*test 2,*//*and more */  2 another_field fixed bin(13)
2 a_really_long_super_long_field_name_requiring_two_lines_for_declaration
    char(1)
2 a_field char(8)

我想出了 3 个单独的正则表达式来获得 3 个部分:

  • ,(?![^(]*\)) - 所有逗号都不在括号中
  • (,(?![^']*')) - 所有逗号都不用单引号
  • (,(?![^\/\*]*\*\/)) - 所有逗号不在评论中

我尝试使用 or (.*?)|(,)|'.*?'|(,)|\/*.*?*\/|(,) 加入他们,但得到以下信息:

1 test fixed
2 another_test char
2 a_third_test
3 one pic
3 two pic
3 three fixed
2 another_field fixed bin
2 a_really_long_super_long_field_name_requiring_a_line_break_...        char
2 a_field char

有没有一种方法可以将这 3 个正则表达式(或者有更好的表达式?)组合起来找到满足所有 3 个的组?

更新:

我可以用一些简单的 java 完成确切的事情,但我想用正则表达式作为学术追求。

String temp = "";
for(String line:text.split("\n")){
  if(line.trim().charAt(line.trim().length()-1) == ',' || line.trim().charAt(line.trim().length()-1) == ';'){
    System.out.println(temp + line);
    temp = "";
  } else {
    temp += line.trim();
  }
}

【问题讨论】:

  • 这是 or 运算符可以提供帮助的地方吗?
  • 这是我尝试的第一件事,使用 (.*?)|(,)|'.*?'|(,)|\/*.*?*\/|(,)我得到:1 test fixed 2 another_test char 2 a_third_test 3 one pic 3 two pic 3 three fixed 2 another_field fixed bin 2 a_really_long_super_long_field_name_requiring_two_lines... char 2 a_field char
  • 这就是问题的主体。
  • 逗号总是在行尾吗?
  • 是的,除了评论。当逗号不在单引号或括号之间时,一行结束。我要解析的文件实际上是旧的 PLi 和 COBOL 结构。声明字段的行将始终以逗号结尾,但以分号结尾的结构的末尾除外。

标签: regex regex-lookarounds regex-greedy regex-group


【解决方案1】:

我想你可能有点想多了。请务必记住,正则表达式是为解析 regular languages 而创建的。当您需要检查您是否在评论或括号内或其他任何内容以了解逗号的含义时,您正在查看的是context-sensitive language(见下图)。

作者:J. Finkelstein(自己的作品)[CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0)

话虽如此,在行尾匹配逗号和分号是很容易的。 /\s*(.*?)[,;]$/gsm 适用于您问题中的测试输入。但是,这并没有考虑到类似

test fixed(5,2),
/* a,
   multi-line,
   comment,
*/

在我看来,解决这个问题的最佳选择是在开始解析 \/\*.*?\*\/ 之前丢弃 cmets。如果您需要保留 cmets,您可能会使用否定的环视方法,但这些方法效率很低,您最好编写一个标记器/解析器。

【讨论】:

  • 我能够使用一些简单的 java 将分隔线分成单独的逗号分隔行,并使用正则表达式从那里获取各个部分。谢谢!
猜你喜欢
  • 2016-12-22
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 1970-01-01
  • 2020-07-04
  • 1970-01-01
相关资源
最近更新 更多