2015-12-25 14 views
7

Sto analizzando il seguente AWS costo tavolo esempio:analisi di un tavolo utilizzando 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'è un file con tali costi:

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

Tuttavia che mi dà:

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

che non è quello che voglio ... Un corretto analizzato values (con il regex corretto) sarebbe guardare l ike questo:

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

Quale sarebbe il diritto regex al fine di ottenere il risultato giusto? Si può supporre che il tavolo avrà sempre lo stesso schema.

+4

I dati reali sono separati con le schede? Ci possono essere casi in cui le colonne sono delimitate solo da uno spazio? – Pietu1998

+0

@ Pietu1998 Principalmente ... ma non necessariamente ... la regex produrrebbe qualcosa di più robusto ... ecco perché non sono passato all'analisi con '\\ t +'. Questi file sono enormi, quindi potrebbe essere inutile cercare quei file per correggere una scheda mancante. – cybertextron

+0

Puoi usare '\\ s {2,}'? –

risposta

4

Dividere di uno oe più spazi. E gli spazi devono apparire nel contesto sottostante.

DIGIT - SPAZI - NON "x"

o

NON

"x" - SPAZI - DIGIT

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

Boom!Grazie mille – cybertextron

+0

@Un'altra cosa ... alcune linee hanno 'EBS Solo $ 0.024', quindi dovrebbe coincidere anche per questo ... in questo caso, '[' Solo EBS ',' $ 0.024 ']' .. Ho provato ad aggiungerlo ma non ha funzionato ... – cybertextron

5

Prova questa violino https://regex101.com/r/sP6zW5/1

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

partita il testo e il gruppo è la vostra lista.

Penso che usare split nel tuo caso sia troppo complicato. Se il testo è sempre lo stesso. Proprio come una procedura inversa di formattazione della stringa.

+0

amow, ancora una cosa ... 'Java' sogna di" sequenza di escape non valida "... come risolverei? – cybertextron

+1

double ogni '\\' – amow

4

Se si vuole usare un'espressione regolare, faresti questo :

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

Nota come ho suddiviso l'espressione regolare per essere leggibile. (Come una lunga stringa, è difficile da leggere/mantenere.) C'è un altro modo di farlo però. Dato che sai quali campi sono stati divisi, puoi semplicemente fare questo semplice split e creare un nuovo array con i valori combinati:

 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)); 
Problemi correlati