我得到以下输入,我想分成四个部分:
-
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
Run Code Online (Sandbox Code Playgroud)
它是METAR,然后是TAF,然后是METAR,然后是TAF.
输入规则:
我想自己抓取每个报告,所以我^(\\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() ) );
Run Code Online (Sandbox Code Playgroud)
它很棒,我得到4个结果:
1:
KPDX 021453Z 16004KT 10SM FEW007 SCT060 BKN200 11/09 A3002 RMK
AO2 SLP166 T01060094 55008
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
3:
KSEA 021453Z 15003KT 10SM FEW035 BKN180 11/09 A3001 RMK AO2
SLP168 60000 T01110089 58010
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我遇到了一个我的正则表达式失败的情况.偶尔,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
Run Code Online (Sandbox Code Playgroud)
发生这种情况时,我得到5个结果:
1:
KPDX 021453Z 16004KT 10SM FEW007 SCT060 BKN200 11/09 A3002 RMK
AO2 SLP166 T01060094 55008
Run Code Online (Sandbox Code Playgroud)
2:
TAF AMD KPDX 021453Z 0215/0312 10005KT P6SM FEW006 SCT060
Run Code Online (Sandbox Code Playgroud)
3:
BKN150
FM021800 11005KT P6SM SCT050 OVC100
FM022200 11007KT P6SM -RA OVC050
FM030500 12005KT P6SM -RA OVC035
Run Code Online (Sandbox Code Playgroud)
4:
KSEA 021453Z 15003KT 10SM FEW035 BKN180 11/09 A3001 RMK AO2
SLP168 60000 T01110089 58010
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
任何人都可以找到一个正确分裂这个奇怪案例的正则表达式吗?或者,我可以尝试在运行正则表达式之前删除输入字符串中的问题换行符,但我无法弄清楚如何检测它.
您可以从以字母开头的行开始。然后收集至少一行,以五个空格开头(您可以轻松地将该条件放宽为至少一个空白字符或其他字符)。然后直到下一行以单词字符开头。
"^(\\w+.*?^[ ]{5}.*?)(?:^\\b|\\Z)"
Run Code Online (Sandbox Code Playgroud)
周围的空间[]不是必需的,但我喜欢将它们包括在内以提高可读性。如果您只想断言有一行以任何空格开头,请替换[ ]{5}为\\s。
请注意,您不必使用捕获组。前瞻将确保您在新报告或文件结尾处结束:
"^\\w+.*?^[ ]{5}.*?(?=^\\b|\\Z)"
Run Code Online (Sandbox Code Playgroud)
这稍微更有效,并且稍微清理了以下代码(因为您可以使用完整匹配而不是检索组。
更新:
为了适应单行报告(一般来说)的可能性,更改结束条件^\\b以匹配新报告的开头就更容易了。根据评论中给出的格式描述,您可以使用:
"^\\w+.*?(?=^(?:SPECI\\s|TAF\\sAMD\\s)?[A-Z]{3,4}\\s\\d+Z|\\Z)"
Run Code Online (Sandbox Code Playgroud)
这需要一个新报告以“可选 SPECI”-“3 或 4 个字母”-“时间戳”或“可选 TAF AMD”-“3 或 4 个字母”-“时间戳”开头。