我得到以下输入,我想分为四个部分:

-
KPDX 021453Z 16004KT 10SM FEW007 SCT060 BKN200 11/09 A3002 RMK
     AO2 SLP166 T01060094 55008
TAF AMD KPDX 021453Z 0215/0312 10005KT P6SM FEW006 SCT060 BKN150
     FM021800 11005KT P6SM SCT050 OVC100
     FM022200 11007KT P6SM -RA OVC050
     FM030500 12005KT P6SM -RA OVC035
KSEA 021453Z 15003KT 10SM FEW035 BKN180 11/09 A3001 RMK AO2
     SLP168 60000 T01110089 58010
TAF AMD KSEA 021501Z 0215/0318 14004KT P6SM SCT020 BKN150
     FM021800 16005KT P6SM SCT025 OVC090
     FM030100 19005KT P6SM OVC070
     FM030200 15005KT P6SM -RA OVC045
     FM030600 16007KT P6SM -RA BKN025 OVC045

是METAR,然后是TAF,然后是METAR,然后是TAF。

输入规则:
  • 机场代码可以更改,但应始终为3或4个字母。
  • METARS将以机场代码或“SPECI”开头,后接机场代码(SPECI KPDX)。
  • TAF将以机场代码或“TAF AMD”开头,然后是机场代码(TAF AMD KPDX)。
  • 在任何报告中,机场代码将始终跟着日期时间戳记。
  • 在TAF中,日期时间戳记后面总是有效时间(例如0215/0318)。
  • 可能只有2个报告,或者多于4个报告。
  • 任何报告都只能是一行。

  • 我想自己获取每个报告,因此我在以下代码中使用regex ^(\\w+.*?)(?:^\\b|\\Z):
    ArrayList<String> reports = new ArrayList<String>();
    Pattern pattern = Pattern.compile( "^(\\w+.*?)(?:^\\b|\\Z)", Pattern.DOTALL|Pattern.MULTILINE );
    Matcher matcher = pattern.matcher( input );
    while( matcher.find() )
        reports.add( new String( matcher.group( 1 ).trim() ) );
    

    效果很好,我得到4个结果:

    1:
    KPDX 021453Z 16004KT 10SM FEW007 SCT060 BKN200 11/09 A3002 RMK
         AO2 SLP166 T01060094 55008
    

    2:
    TAF AMD KPDX 021453Z 0215/0312 10005KT P6SM FEW006 SCT060 BKN150
         FM021800 11005KT P6SM SCT050 OVC100
         FM022200 11007KT P6SM -RA OVC050
         FM030500 12005KT P6SM -RA OVC035
    

    3:
    KSEA 021453Z 15003KT 10SM FEW035 BKN180 11/09 A3001 RMK AO2
         SLP168 60000 T01110089 58010
    

    4:
    TAF AMD KSEA 021501Z 0215/0318 14004KT P6SM SCT020 BKN150
         FM021800 16005KT P6SM SCT025 OVC090
         FM030100 19005KT P6SM OVC070
         FM030200 15005KT P6SM -RA OVC045
         FM030600 16007KT P6SM -RA BKN025 OVC045
    

    我遇到了我的正则表达式失败的情况。有时,一条TAF线会运行得太长并且会被缠绕(我对此无能为力),因此它看起来像(请注意“TAF AMD PDX”正下方的“BKN150”):
    -
    KPDX 021453Z 16004KT 10SM FEW007 SCT060 BKN200 11/09 A3002 RMK
         AO2 SLP166 T01060094 55008
    TAF AMD KPDX 021453Z 0215/0312 10005KT P6SM FEW006 SCT060
    BKN150
         FM021800 11005KT P6SM SCT050 OVC100
         FM022200 11007KT P6SM -RA OVC050
         FM030500 12005KT P6SM -RA OVC035
    KSEA 021453Z 15003KT 10SM FEW035 BKN180 11/09 A3001 RMK AO2
         SLP168 60000 T01110089 58010
    TAF AMD KSEA 021501Z 0215/0318 14004KT P6SM SCT020 BKN150
         FM021800 16005KT P6SM SCT025 OVC090
         FM030100 19005KT P6SM OVC070
         FM030200 15005KT P6SM -RA OVC045
         FM030600 16007KT P6SM -RA BKN025 OVC045
    

    发生这种情况时,我得到5个结果:

    1:
    KPDX 021453Z 16004KT 10SM FEW007 SCT060 BKN200 11/09 A3002 RMK
         AO2 SLP166 T01060094 55008
    

    2:
    TAF AMD KPDX 021453Z 0215/0312 10005KT P6SM FEW006 SCT060
    

    3:
    BKN150
         FM021800 11005KT P6SM SCT050 OVC100
         FM022200 11007KT P6SM -RA OVC050
         FM030500 12005KT P6SM -RA OVC035
    

    4:
    KSEA 021453Z 15003KT 10SM FEW035 BKN180 11/09 A3001 RMK AO2
         SLP168 60000 T01110089 58010
    

    5:
    TAF AMD KSEA 021501Z 0215/0318 14004KT P6SM SCT020 BKN150
         FM021800 16005KT P6SM SCT025 OVC090
         FM030100 19005KT P6SM OVC070
         FM030200 15005KT P6SM -RA OVC045
         FM030600 16007KT P6SM -RA BKN025 OVC045
    

    谁能找出能正确分割这种奇怪情况的正则表达式?或者,我可以尝试在运行正则表达式之前删除输入字符串中的问题换行符,但是我不知道如何检测到它。

    最佳答案

    您可以从以字母开头的行开始。然后收集至少一行以五个空格开头的行(您可以轻松地将该条件放宽为至少一个空白字符或其他内容)。然后转到下一个以单词字符开头的行。

    "^(\\w+.*?^[ ]{5}.*?)(?:^\\b|\\Z)"
    

    空格周围的[]并不是必需的,但出于可读性考虑,我希望将其包括在内。如果只想断言一行以任何空格开头,请将[ ]{5}替换为\\s

    请注意,您不必使用捕获组。前瞻性操作将确保您结束于新报告或文件末尾的位置:
    "^\\w+.*?^[ ]{5}.*?(?=^\\b|\\Z)"
    

    这会稍微提高效率,并稍微清理一下以下代码(因为您可以使用完全匹配而不是检索组。

    更新:

    为了适应单行报告的可能性(通常),更改结束条件^\\b以匹配新报告的开始甚至更加容易。根据注释中给出的格式描述,可以使用:
    "^\\w+.*?(?=^(?:SPECI\\s|TAF\\sAMD\\s)?[A-Z]{3,4}\\s\\d+Z|\\Z)"
    

    这需要新的报告以“可选SPECI”-“3或4个字母”-“时间戳”或“可选TAF AMD”-“3或4个字母”-“时间戳”开头。

    关于java - 拆分METAR/TAF,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13202096/

    10-10 11:50