2015-12-25 11 views
7

Tôi đang phân tích các bảng dụ AWS chi phí sau:Phân tích một bảng sử dụng regex - Java

m1.small 1 1 1.7  1 x 160 $0.044 per Hour 
m1.medium 1 2 3.75 1 x 410 $0.087 per Hour 
m1.large 2 4 7.5  2 x 420 $0.175 per Hour 
m1.xlarge 4 8 15  4 x 420 $0.35 per Hour 

Có một tập tin với những chi phí:

input = new Scanner(file); 
String[] values; 
while (input.hasNextLine()) { 
    String line = input.nextLine(); 
    values = line.split("\\s+"); // <-- not what I want... 
    for (String v : values) 
     System.out.println(v); 
} 

Tuy nhiên điều đó mang lại cho tôi:

m1.small 
1 
1 
1.7 
1 
x 
160 
$0.044 
per 
Hour 

đó không phải là những gì tôi muốn ... Đã sửa lỗi được phân tích values (với đúng regex) sẽ xem ike này:

['m1.small', '1', '1', '1.7', '1 x 160', '$0.044', 'per Hour'] 

Điều gì sẽ là đúng regex để có được kết quả phù hợp? Người ta có thể giả định rằng bảng sẽ luôn có cùng một mẫu.

+4

Dữ liệu thực tế có được phân tách bằng tab không? Có thể có các trường hợp các cột chỉ được phân tách bằng một dấu cách không? – Pietu1998

+0

@ Pietu1998 Chủ yếu là ... nhưng không nhất thiết ... regex sẽ tạo ra thứ gì đó mạnh mẽ hơn ... đó là lý do tại sao tôi không di chuyển để phân tích cú pháp với '\\ t +'. Các tệp đó rất lớn, do đó, có thể tìm kiếm các tệp đó vô nghĩa để sửa một tab bị thiếu. – cybertextron

+0

Bạn có thể sử dụng '\\ s {2,}' không? –

Trả lời

4

Tách một không gian khác. Và các khoảng trắng phải xuất hiện trong ngữ cảnh bên dưới.

DIGIT - không gian - KHÔNG "x"

hoặc

KHÔNG "x" - không gian - DIGIT

values = line.split("(?<=\\d)\\s+(?=[^x])|(?<=[^x])\\s+(?=\\d)"))); 
+0

Bùng nổ!Cảm ơn bạn rất nhiều – cybertextron

+0

@ Chỉ cần một điều nữa ... một số dòng có 'EBS Chỉ $ 0,024', do đó, nó phải phù hợp cho rằng quá ... trong trường hợp này,' ['EBS Only', '$ 0,024'] '.. Tôi đã cố gắng thêm nhưng không hoạt động ... – cybertextron

5

Hãy thử fiddle này https://regex101.com/r/sP6zW5/1

([^\s]+)\s+(\d+)\s+(\d+)\s+([\d\.]+)\s+(\d+ x \d+)\s+(\$\d+\.\d+)\s+(per \w+)

trận đấu văn bản và nhóm là danh sách của bạn.

Tôi nghĩ việc chia nhỏ trong trường hợp của bạn quá phức tạp. Nếu văn bản luôn giống nhau. Chỉ cần làm thủ tục đảo ngược định dạng chuỗi.

+0

amow, một điều nữa ... 'Java' đang bitching về' chuỗi thoát không hợp lệ' ... làm cách nào tôi sửa lỗi đó? – cybertextron

+1

tăng gấp đôi mỗi '\\' – amow

4

Nếu bạn muốn sử dụng một biểu thức chính quy, bạn muốn làm điều này :

 String s = "m1.small 1 1 1.7  1 x 160 $0.044 per Hour"; 
     String spaces = "\\s+"; 
     String type = "(.*?)"; 
     String intNumber = "(\\d+)"; 
     String doubleNumber = "([0-9.]+)"; 
     String dollarNumber = "([$0-9.]+)"; 
     String aXb = "(\\d+ x \\d+)"; 
     String rest = "(.*)"; 

     Pattern pattern = Pattern.compile(type + spaces + intNumber + spaces + intNumber + spaces + doubleNumber 
       + spaces + aXb + spaces + dollarNumber + spaces + rest); 
     Matcher matcher = pattern.matcher(s); 
     while (matcher.find()) { 
      String[] fields = new String[] { matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), 
        matcher.group(5), matcher.group(6), matcher.group(7) }; 
      System.out.println(Arrays.toString(fields)); 
     } 

Lưu ý cách tôi chia nhỏ biểu thức chính quy để có thể đọc được. (Như một String dài, rất khó để đọc/duy trì.) Có một cách khác để làm điều đó mặc dù. Vì bạn biết trường nào đang được tách ra, bạn chỉ có thể thực hiện phân chia đơn giản này và tạo một mảng mới với các giá trị được kết hợp:

 String[] allFields = s.split("\\s+"); 
     String[] result = new String[] { 
      allFields[0], 
      allFields[1], 
      allFields[2], 
      allFields[3], 
      allFields[4] + " " + allFields[5] + " " + allFields[6],   
      allFields[7], 
      allFields[8] + " " + allFields[9] }; 
     System.out.println(Arrays.toString(result)); 
Các vấn đề liên quan