Autore Topic: di nuovo regex :-)  (Letto 613 volte)

Offline Trigun

  • Utente normale
  • ***
  • Post: 183
  • Respect: +4
    • Mostra profilo
di nuovo regex :-)
« il: 19 Gennaio 2012, 15:40:54 CET »
0
ho ancora 1 problema con una stringa regex...


ho queste righe:
Codice: [Seleziona]
     ý000016.01     0,14PZ    (10,8 %)               PALLET(Colli5025916105211IVA
Codice: [Seleziona]
     ý000016.01     PZ    0,16(10,8 %)               PALLET(Colli5025916105211IVA
Codice: [Seleziona]
     ý000016.01     PZ   0,16               PALLET(Colli5025916105211IVA
sto cercando di estrapolare da questa riga delle variabili
il numero iniziale è standard e non ci sono problemi...
i problemi sono su gli altri dati che possono esserci o meno...

con questa dovrei prendere quel 0,14PZ o semplicemente PZ se non c'e' il 0,14
Codice: [Seleziona]
prezzo = texts[i].replaceAll(
                                                                ".*((\\d{1,3}\\,\\d{2})?(PZ|KG)).*", "$1");

poi con questa vado a prendere la roba nelle parentesi
Codice: [Seleziona]
Pattern p2 = Pattern.compile(".*\\((.*\\%)\\).*");
if (p2.matcher(texts[i]).matches()){
                                                //        ricavo = p2.matcher(texts[i]).group();
                                                        ricavo = texts[i].replaceAll(".*\\((.*\\%)\\).*", "$1");
                                                }
else{
                                                        ricavo = "";
                                                }

e per l'altro numero ancora non ho provato manco a farlo :-)


il problema cmq è nell'estrazione del prezzo... in quanto se il prezzo non c'e' dovrebbe estrarmi solo PZ (o KG) mentre se c'e' mi dovrebbe dare 0,14PZ ... mentre al momento mi stampa sempre e solo PZ (o KG)... il numero lo ignora... dove sbaglio?


*edit prima di postare quindi non è un edit*
ho risolto il problema mettendo .*? e quindi mandando il primo "tutto" in lazy... però non ho capito perché effettivamente non mi funzionava prima... non dovrebbe essere gready la condizione :
Codice: [Seleziona]
((\\d{1,3}\\,\\d{2})?
quindi se così fosse avrebbe prima di tutto controllato se poteva prenderlo e poi avrebbe provato senza ... o no?

Offline Trigun

  • Utente normale
  • ***
  • Post: 183
  • Respect: +4
    • Mostra profilo
Re:di nuovo regex :-)
« Risposta #1 il: 19 Gennaio 2012, 16:40:02 CET »
0
tra l'altro ho notato che se uso {1,3} mi matcha 1 carattere anche se ce ne sono 2... perché è sempre in lazy? di default non dovrebbe essere il contrario?

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:di nuovo regex :-)
« Risposta #2 il: 19 Gennaio 2012, 17:31:54 CET »
0
Ti consiglio di leggerti bene la documentazione delle regular expression, sono collaudatissime da decenni e hanno sempre ragione loro ;-)

Prova con:
Codice: [Seleziona]
".*(\\d{1,3},\\d{2}(PZ|KG)).*"è inutile fare 3 match di cui 2 annidati quando ne bastano 2, la virgola in quel contesto significa virgola quindi "\\," è inutile.

L'uso {1,3} non è lazy significa da 1 a 3 volte. Il match singolo è obbligato se incontra "0,14PZ", c'è un sola cifra prima della virgola.
adb logcat | tee /tmp/logcat | grep TAG

Offline Trigun

  • Utente normale
  • ***
  • Post: 183
  • Respect: +4
    • Mostra profilo
Re:di nuovo regex :-)
« Risposta #3 il: 19 Gennaio 2012, 17:43:40 CET »
0
praticamente hai tolto il "()?" in questo modo non andrebbe a matchare la 3° riga

cmq la stringa che funziona è questa :
Codice: [Seleziona]
".*?((\\d{1,3}\\,\\d{2})?(PZ|KG)).*"e come si nota ho dovuto mettere il lazy al primo elemento per farlo funzionare... cmq ora ripensandoci ho anche capito il motivo :-)

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:di nuovo regex :-)
« Risposta #4 il: 19 Gennaio 2012, 19:57:37 CET »
+1
Io consideravo il numero con l'unità di misura, invece vuoi l'unità di misura e eventualmente il numero.

Se metti ".*" come inizio è greedy quindi il match è su tutta la riga, poi comincia a ridurlo col rischio di prendere lui una parte dei numeri iniziali. Consiglio di sfruttare il fatto che i numeri iniziano prima con uno spazio. E' inutile annidare i match basta individuare il numero ($1) se è presente e l'unità di misura ($2):

Codice: [Seleziona]
texts[i] = texts[i].replaceAll(".*\\s+(\\d{1,3},\\d{2})?(PZ|KG).*", "$1$2");
adb logcat | tee /tmp/logcat | grep TAG