5

4つの部分に分割したい次の入力を取得します。

-
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です。

入力ルール:

  1. 空港コードは変更される可能性がありますが、常に3文字または4文字である必要があります。
  2. METARSは、空港コード、または「SPECI」の後に空港コード(SPECI KPDX)のいずれかで始まります。
  3. TAFは、空港コード、または「TAF AMD」の後に空港コード(TAF AMD KPDX)のいずれかで始まります。
  4. どのレポートでも、空港コードの後に​​は常に日時スタンプが続きます。
  5. TAFでは、日時スタンプの後に常に有効な時刻が続きます(たとえば、0215/0318)。
  6. レポートは2つだけ、または4つ以上になる可能性があります。
  7. レポートは1行だけにすることができます。

各レポートを単独で取得したいので^(\\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 AMDPDX」のすぐ下にある「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

この奇妙なケースを正しく分割する正規表現を誰かが理解できますか?または、正規表現を実行する前に、入力文字列の問題のある改行を削除しようとすることもできますが、それを検出する方法がわかりません。

4

1 に答える 1

2

文字で始まる行から始めることができます。次に、5つのスペースで始まる少なくとも1つの行を収集します(その条件を少なくとも1つの空白文字などに簡単に緩めることができます)。そして、単語文字で始まる次の行まで進みます。

"^(\\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文字」-「タイムスタンプ」または「オプションのTAFAMD」-「3文字または4文字」-「タイムスタンプ」のいずれかで始まる新しいレポートが必要です。

于 2012-11-02T19:57:54.050 に答える