Java 用于解析格式化数字的正则表达式

Java 用于解析格式化数字的正则表达式,java,regex,Java,Regex,我正在分析包含大量格式化数字的文档,例如: Frc consts -- 1.4362 1.4362 5.4100 IR Inten -- 0.0000 0.0000 0.0000 Atom AN X Y Z X Y Z X Y Z 1

我正在分析包含大量格式化数字的文档,例如:

 Frc consts  --     1.4362                 1.4362                 5.4100
 IR Inten    --     0.0000                 0.0000                 0.0000
 Atom AN      X      Y      Z        X      Y      Z        X      Y      Z
    1   6     0.00   0.00   0.00     0.00   0.00   0.00     0.00   0.00   0.00
    2   1     0.40  -0.20   0.23    -0.30  -0.18   0.36     0.06   0.42   0.26
这些是分隔的行,所有行都有一个重要的前导空格,可能有也可能没有重要的尾随空格)。它们由72、72、78、78和78个字符组成。我可以推断场之间的边界。这些可通过以下方式描述(使用fortran格式(nx=nspaces,an=n alphanum,in=n列中的整数,fm.n=m个字符的浮点,小数点后有n位):

我可能有几千种不同的格式(我可以自动生成或分包),并通过描述组件的正则表达式来描述它们。因此,如果regf10_4表示满足f10.4约束的任何字符串的正则表达式,我可以创建以下形式的正则表达式:

COMMENTS 
      (\s
      .{14}
      \s
      regf10_4,
      \s{13}
      regf10_4,
      \s{13}
      regf10_4,
)
我想知道是否有这样的正则表达式可以满足重复使用。计算机和人类创建与f10.4兼容的数字的方式有很多种。我相信以下都是fortran的合法输入和/或输出(我不需要像12.4f那样的f或d形式的后缀)[SO中的格式应理解为第一个无前导空格,第二个无前导空格,以此类推]

-1234.5678
 1234.5678
            // missing number
 12345678.
 1.
 1.0000000
    1.0000
        1.
 0.
        0.
     .1234
    -.1234
    1E2
    1.E2
    1.E02
  -1.0E-02
**********  // number over/underflow
它们必须对相邻字段的内容具有鲁棒性(例如,仅在精确位置检查10个字符。因此,以下内容适用于(a1、f5.2、a1):


我使用的是Java,因此需要与Java 1.6兼容的正则表达式结构(例如,不是perl扩展)

您可以从这里开始,然后从那里开始

此正则表达式匹配您提供的所有数字。
不幸的是,它还与31.23中的3相匹配-


这只是一个部分答案,但Java 1.5提醒了我,它可以扫描文本并解释数字,这为这个Java实用程序可以扫描和解释的数字提供了一个BNF。原则上,我想象BNF可以用来构造一个正则表达式。

据我所知,每行包含一个或多个固定宽度的字段,这些字段可能包含标签、空格或不同类型的数据。如果您知道字段的宽度和类型,提取它们的数据只需
substring()
trim()
和(可选)
Whatever.parsewhater()
。正则表达式无法使这项工作变得更简单,事实上,它们所能做的只是让它变得更难

Scanner也没有真正的帮助。没错,它为各种值类型预定义了正则表达式,并为您进行转换,但每次都需要告诉它要查找哪种类型,并且它需要用它可以识别的分隔符分隔字段。根据定义,固定宽度数据不需要分隔符。您可能是ab通过对行中应保留的字符数进行前瞻,可以伪造分隔符,但这只是另一种使工作比需要更困难的方法


听起来性能将是一个主要问题;即使你可以让正则表达式解决方案工作,它也可能太慢了。这不是因为正则表达式天生就很慢,而是因为你必须通过扭曲才能使它们适应问题。我建议你在这项工作中忘记正则表达式。

+1尽可能完整,但我担心这么完整,你可能已经模糊了你真正想要的。作为一个人,我可以构造一个正则表达式,从你提供的示例中获取数字,但是对于所有fortran的东西,我怀疑这是否是你想要的。如果你只是给我们一堆字符串,以及你期望的结果呢?谢谢。我想要(a)测试包含我想要的组件的行,以及(b)提取我然后使用Java解析的字段,例如parseDouble(group(I).trim())并捕获异常。星号作为一种特殊情况处理您是否有类似
(1x,a4,a4,3(2x,3a7))的格式规范
对于每一行,提前?或者你必须推断出这是解析任务的一部分吗?我有所有需要的格式,但不知道它们何时从一个转换到另一个(我有一个框架来管理)。[我也在推断格式,但我使用不同的方法,如动态编程].虽然原则上我可以提取字段并尝试tp解析,但还有其他字段(包含更多文本)其中正则表达式是最简单的方法谢谢-这是正则表达式构造的有用注释。不幸的是,由于下面回答了自己的问题,因此截断了一些代码+1,我相信这将使操作走上正确的轨道。谢谢。我同意这可能是解决上述问题的最佳方法。不幸的是,g一般的问题是,有些输出使用空格分隔而不是格式,我正在寻找一个通用的解决方案。[您对从同一来源的文档库中自动提取格式有何想法?]如果我是你的话,我会寻找一个平面文件解析库,虽然现在似乎没有很多这样的库(对于Java来说)。但是如果你必须从头开始创建解决方案,不要基于正则表达式。至于格式的自动提取…可能是Perl.:-/
-1234.5678
 1234.5678
            // missing number
 12345678.
 1.
 1.0000000
    1.0000
        1.
 0.
        0.
     .1234
    -.1234
    1E2
    1.E2
    1.E02
  -1.0E-02
**********  // number over/underflow
a-1.23b   // -1.23
- 1.23.   // 1.23
3 1.23-   // 1.23
// [-+]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][-+]?[0-9]+)?
// 
// Match a single character present in the list “-+” «[-+]?»
//    Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
// Match the regular expression below «(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)»
//    Match either the regular expression below (attempting the next alternative only if this one fails) «[0-9]+(?:\.[0-9]*)?»
//       Match a single character in the range between “0” and “9” «[0-9]+»
//          Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
//       Match the regular expression below «(?:\.[0-9]*)?»
//          Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//          Match the character “.” literally «\.»
//          Match a single character in the range between “0” and “9” «[0-9]*»
//             Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
//    Or match regular expression number 2 below (the entire group fails if this one fails to match) «\.[0-9]+»
//       Match the character “.” literally «\.»
//       Match a single character in the range between “0” and “9” «[0-9]+»
//          Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
// Match the regular expression below «(?:[eE][-+]?[0-9]+)?»
//    Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single character present in the list “eE” «[eE]»
//    Match a single character present in the list “-+” «[-+]?»
//       Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single character in the range between “0” and “9” «[0-9]+»
//       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Pattern regex = Pattern.compile("[-+]?(?:[0-9]+(?:\\.[0-9]*)?|\\.[0-9]+)(?:[eE][-+]?[0-9]+)?");
Matcher matcher = regex.matcher(document);
while (matcher.find()) {
    // matched text: matcher.group()
    // match start: matcher.start()
    // match end: matcher.end()
}