2012-11-02 17 views
5

tôi nhận được đầu vào sau đây mà tôi muốn chia thành bốn phần:tách ra METARs/TAFs

- 
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 

Đó là một METAR, sau đó một TAF, sau đó một METAR, sau đó một TAF.

quy tắc Input:

  1. Các mã sân bay có thể thay đổi, nhưng phải luôn luôn được 3 hoặc 4 chữ cái.
  2. METARS sẽ bắt đầu bằng mã sân bay hoặc "SPECI" theo sau là mã sân bay (SPECI KPDX).
  3. TAF sẽ bắt đầu bằng mã sân bay hoặc "TAF AMD" theo sau là mã sân bay (TAF AMD KPDX).
  4. Trong bất kỳ báo cáo nào, mã sân bay sẽ luôn được theo sau bởi dấu ngày giờ.
  5. Trong TAF, dấu ngày giờ sẽ luôn được theo sau bởi thời gian hợp lệ (ví dụ: 0215/0318).
  6. Chỉ có thể có tối thiểu 2 báo cáo hoặc nhiều hơn 4 báo cáo.
  7. Mọi báo cáo có thể chỉ là một dòng.

Tôi muốn lấy mỗi báo cáo của chính nó, vì vậy tôi đang sử dụng regex ^(\\w+.*?)(?:^\\b|\\Z) trong đoạn mã sau:

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())); 

Nó hoạt động tuyệt vời, tôi nhận được 4 kết quả:

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 

Tôi đã gặp một trường hợp regex của tôi thất bại.Thỉnh thoảng, một dòng TAF sẽ chạy quá dài và sẽ được bao bọc (Tôi đã không kiểm soát này), vì vậy nó có thể trông giống như (chú ý "BKN150" ngay bên dưới "TAF AMD PDX"):

- 
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 

Khi điều này xảy ra, tôi nhận được 5 kết quả:

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 

bất cứ ai có thể hình dung ra một regex đúng sẽ chia trường hợp kỳ lạ này? Ngoài ra tôi có thể cố gắng để loại bỏ sự cố ngắt dòng trong chuỗi đầu vào trước khi chạy regex trên nó, nhưng tôi không thể tìm ra cách để phát hiện nó.

Trả lời

2

Bạn có thể bắt đầu bằng một dòng bắt đầu bằng một chữ cái. Sau đó thu thập ít nhất một dòng, bắt đầu bằng năm dấu cách (bạn có thể dễ dàng nới lỏng điều kiện đó với ít nhất một ký tự trắng hoặc một cái gì đó). Và sau đó đi cho đến khi dòng tiếp theo bắt đầu bằng một ký tự từ.

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

[] xung quanh không gian là không cần thiết, nhưng tôi muốn bao gồm chúng để dễ đọc. Nếu bạn chỉ muốn khẳng định, có một dòng bắt đầu với bất kỳ khoảng trống nào, hãy thay thế [ ]{5} theo \\s.

Lưu ý rằng bạn không phải sử dụng nhóm chụp. Một lookahead sẽ đảm bảo rằng bạn kết thúc ở vị trí đó được theo sau bởi một trong hai báo cáo mới hoặc cuối của tập tin:

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

Đây là một chút hiệu quả hơn và dọn dẹp đoạn mã sau một chút (vì bạn có thể sử dụng các trận đấu đầy đủ thay vì lấy nhóm

cập nhật:.

để thích ứng với khả năng báo cáo single-line (và nói chung) nó thậm chí còn dễ dàng hơn, để thay đổi tình trạng kết thúc ^\\b để phù hợp với bắt đầu một báo cáo mới Theo định dạng descri ption đưa ra trong các bình luận, bạn có thể sử dụng:

"^\\w+.*?(?=^(?:SPECI\\s|TAF\\sAMD\\s)?[A-Z]{3,4}\\s\\d+Z|\\Z)" 

Điều này đòi hỏi một báo cáo mới để bắt đầu với một trong hai "SPECI tùy chọn" - "3 hoặc 4 chữ cái" - "dấu thời gian" hay "tùy chọn TAF AMD" - "3 hoặc 4 chữ cái "-" dấu thời gian ".

+0

Điều đó có hiệu quả, ngoại trừ một trường hợp có thể xảy ra khác mà tôi đã bỏ qua. Bất kỳ một trong các báo cáo chỉ có thể là một dòng duy nhất và giải pháp của bạn không thành công trong trường hợp đó. Tôi sẽ chỉnh sửa câu hỏi của tôi để bao gồm khả năng đó. – Ralgha

+0

Sau đó, làm cách nào bạn có thể phân biệt các báo cáo một dòng từ các báo cáo xung quanh (cú pháp)? –

+0

Quy tắc định dạng nhất quán, METAR sẽ luôn bắt đầu bằng mã sân bay hoặc mã sân bay "SPECI", theo sau là dấu ngày/giờ.Tương tự như vậy, TAF luôn bắt đầu bằng mã sân bay hoặc mã sân bay "TAF AMD", theo sau là dấu ngày/giờ. Dấu thời gian trong TAF sẽ luôn được theo sau bởi thời gian hợp lệ (ví dụ: 0215/0318). – Ralgha

Các vấn đề liên quan