【发布时间】:2011-05-27 17:14:10
【问题描述】:
我有以下用于数据验证的正则表达式:
lexer = /(?:
(.{18}|(?:.*)(?=\s\S{2,})|(?:[^\s+]\s){1,})\s*
(.{18}|(?:.*)(?=\s\S{2,})|(?:[^\s+]\s){1,})\s*
(?:\s+([A-Za-z][A-Za-z0-9]{2}(?=\s))|(\s+))\s*
(Z(?:RO[A-DHJ]|EQ[A-C]|HIB|PRO|PRP|RMA)|H(?:IB[2E]|ALB)|F(?:ER[2T]|LUP2|ST4Q))\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\s+\d{10}|\s+)\s*
(\d{6})\s*
(.*)(?=((?:\d{2}\/){2}\d{4}))\s*
((?:\d{2}\/){2}\d{4})\s*
(\S+)
)/x
问题是我必须遍历一个有 10000 行(平均)的文件,使用正则表达式执行验证,导致解析应用程序速度缓慢。
filename = File.new(@file, "r")
filename.each_line.with_index do |line, index|
next if index < INFO_AT + 1
lexer = /(?:
(.{18}|(?:.*)(?=\s\S{2,})|(?:[^\s+]\s){1,})\s*
(.{18}|(?:.*)(?=\s\S{2,})|(?:[^\s+]\s){1,})\s*
(?:\s+([A-Za-z][A-Za-z0-9]{2}(?=\s))|(\s+))\s*
(Z(?:RO[A-DHJ]|EQ[A-C]|HIB|PRO|PRP|RMA)|H(?:IB[2E]|ALB)|F(?:ER[2T]|LUP2|ST4Q))\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\S+)\s*
(\s+\d{10}|\s+)\s*
(\d{6})\s*
(.*)(?=((?:\d{2}\/){2}\d{4}))\s*
((?:\d{2}\/){2}\d{4})\s*
(\S+)
)/x
m = lexer.match(line)
begin
if (m) then ...
编辑 在这里你可以找到一些我需要解析的行:File
编辑 II @迈克R
我正在解析一个每行包含 25 列的文件,每列可能有自己的验证方式。它可以是空格或完整的字符集。
- 需要进行验证,因为我必须删除与该部分不匹配的行。
- 可能没有必要
- 这是必要的
我不相信它的表达式构造不好,它使用的前瞻,也许在我重复代码的部分(我只是不记得捕获组索引 \1...\n,如果这个就是你的意思!)我也相信这里正在发生灾难性的回溯。
如果您看到该文件,也许您会明白我为什么要这样做!让我们以第一列为例。我必须匹配“零件编号”,并且我没有任何关于如何执行此操作的规则,例如:
- 123456789
- 1 555 989
- 0123456789123456789
简单的 \S+ 或 (\S+\s){1, } 都不能解决这个问题,因为我不会保证数据的完整性。
泰!
有什么改进、建议吗?
~埃德奎尼翁
【问题讨论】:
-
嗯...写一个真正的解析器,也许吧?那个正则表达式是一个完全不可读的怪物。
-
哇哇哇。怎么回事?为什么不是所有
(\S+)\s*都折叠成(?:(\S+)\s*)+? -
那些
(\S+)\s*肯定应该是(\S+)\s+。这将为您节省很多痛苦。但我认为这不是最好的方法。 -
@Eder:你能举一些你想要匹配的例子吗?
-
@rockerest: "(\S+)\s*" 这真的很有必要,因为我必须捕获这么多的匹配项
标签: ruby regex parsing jruby token