Non conoscendo le espressioni regolari, ci sto diventando scemo: :hard:
ho necessità di tramutare in modo dinamico una stringa che può essere:
"===== 23.8.1.1 Progetto Diagramma in Linea ====="
ma anche:
"===== 1 Primo Capitolo ====="
oppure:
"===== 1.2.1 Qualsiasi cosa ====="
o anche:
"===== 12.21.1.15 Qualsiasi cosa ====="
e via discorrendo...
in queste stringhe:
"k23/k23.8/k23.8.1/k23.8.1.1"
"k1"
"k1/k1.2/k1.2.1"
"k12/k12.21/k12.21.1/k12.21.1.15"
Qualcuno la fuori che conosce il componente gb.pcre
http://gambaswiki.org/wiki/comp/gb.pcre/regexp
e i metodi match e replace di regexp, può cortesemente aiutarmi?
:ciao:
Non ci sono 'regexp' qui, ma questo funziona.
Public Sub Form_Open()
Print GetKIP("===== 23.8.1.1 Progetto Diagramma In Linea =====")
Print GetKIP("===== 1 Primo Capitolo =====")
Print GetKIP("===== 1.2.1 Qualsiasi cosa =====")
Print GetKIP("===== 12.21.1.15 Qualsiasi cosa =====")
End
Public Sub GetKIP(sLine As String) As String
Dim sNew, sWork As String
Dim iLoop, iLetter As Integer
Dim sHold As New String[]
For iLetter = 1 To Len(sLine)
If IsNumber(Mid(sLine, iLetter, 1)) Then sWork &= Mid(sLine, iLetter, 1)
Next
sWork = "k" & sWork
sHold = Split(sWork, ".")
For iLoop = 0 To sHold.Max
If iLoop = 0 Then sNew &= sHold[0] & "/"
If iLoop = 1 Then sNew &= sHold[0] & "." & sHold[1] & "/"
If iLoop = 2 Then sNew &= sHold[0] & "." & sHold[1] & "." & sHold[2] & "/"
If iLoop = 3 Then sNew &= sHold[0] & "." & sHold[1] & "." & sHold[2] & "." & sHold[3] & "/"
Next
Return Left(sNew, -1)
End
Uscita: -
k23/k23.8/k23.8.1/k23.8.1.1
k1
k1/k1.2/k1.2.1
k12/k12.21/k12.21.1/k12.21.1.15
@cogier
ti ringrazio molto, ma io sto cercando una soluzione con le regexp :-\
Mi pare che tu stia usando la sintassi che usa per LIKE piuttosto che quella piu' adatta alle REGEX. Non ho pratica con queste su Gambas (poco anche in Python a dire il vero), ma forse la cosa piu' semplice sarebbe dividere il testo riga per riga, almeno ti eviti complicazioni con le opzioni, e poi cercare il blocco comprensivo dei 4 segni di uguale dalle parti. Se ti basta quello, lo trovi con qualcosa tipo
regexp(text, "( ====|====) .* ====)
o forse meglio ancora meglio sarebbe usare i capturing groups, che nel caso di una riga tipo
potrebbero essere rintracciati con una regexp tipo
[\s]{0,1}==== ([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{1,2}) ====
che sembra complicata, ma in realta' sta a significare una riga con uno spazio o meno all'inizio, poi quattro segni di uguale, uno spazio, poi ci sono tre gruppi di uno o due numeri separati da un punto, altro spazio e infine altri quattro uguale. Manca ancora qualche cosa, tipo il dire se quello deve essere l'inizio della riga etc etc. La soluzione ideale sarebbe usare la regexp multilinea, iterare i Match e sostituire i capturing groups. La cosa piu' semplice rimane la prima, secondo me, anche perche' come dicevo con le regex di Gambas ho zero esperienze. Ricorda comunque il racconto: Avevo un problema, ho cercato di risolverlo con le regex, adesso ho due problemi. Di sicuro farai molti tentativi su siti tipo https://regex101.com (https://regex101.com)
Per ora ho questa soluzione, cosa te ne pare?
Perche' no? Casomai cambierei i [1-9][1-9][1-9] in [1-9]{1,3} (o forse intendi [0-9]?), solo per ridurre la lunghezza delle righe. Per il resto, se non hai da processare milioni di righe (le regex sono piuttosto lente), se va bene lascerei stare.
Si avevi ragione ci sono capitoli .0 pertanto occorre cercare [0-9]
Invece riguardo alla riduzione non ci sono riuscito :-\
Questo è il massimo che sono riuscito a fare
Public Sub Main()
Print Capitolo(" ===== 23.8.1.1 Progetto Diagramma in Linea numero 2 =====")
Print Capitolo(" ===== 23.8.1 Progetto Diagramma in Linea numero 2 =====")
Print Capitolo(" ===== 23.8 Progetto Diagramma in Linea numero 2 =====")
Print Capitolo(" ===== 23 Progetto Diagramma in Linea numero 2 =====")
Print Capitolo(" ===== 1 Progetto Diagramma in Linea numero 2 =====")
Print Capitolo("===== 12.4.4.2 Eigene Dialoge - Projekt 2 =====")
Print Capitolo("===== 1.1 Capitolo =====")
Print Capitolo(" ===== 1.1.3 Gambas im Internet ===== ")
Print Capitolo("===== 13 Capitolo =====")
Print Capitolo("===== 10.1 Capitolo =====")
Print Capitolo("===== 22.5.4 Capitolo =====")
Print Capitolo("=====24.7.8.4 Capitolo =====") ' <--------------------------------così prima non funzionava, ora funziona
Print Capitolo("===== 22.10.0.2 Methoden der Klasse Memcached ===== ") ' <-----c'è anche il capitolo 0 ;-D
Print Capitolo("=====24.7.8.4Capitolo =====")
End
Private Sub Capitolo(value As String) As String
'' così sembra funzionare tutto bene
If Trim(value) Begins "=====" Then
value = Replace$(value, "=====", "")
If RegExp.Match(value, "([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9])") Then
Print "MATCH"
value = RegExp.Replace(value, "([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9])", " k&1/k&1.&2/k&1.&2.&3/k&1.&2.&3.&4 ")
Else If RegExp.Match(value, "([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9])") Then
Print "MATCH"
value = RegExp.Replace(value, "([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9])", " k&1/k&1.&2/k&1.&2.&3 ")
Else If RegExp.Match(value, "([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9])") Then
Print "MATCH"
value = RegExp.Replace(value, "([0-9][0-9]|[0-9]).([0-9][0-9]|[0-9])", " k&1/k&1.&2 ")
Else If RegExp.Match(value, "([0-9][0-9]|[0-9])") Then
Print "MATCH"
value = RegExp.Replace(value, "([0-9][0-9]|[0-9])", " k&1 ")
Endif
value = Scan(value, "* * *")[1]
Endif
Return value
End
Con questo codice considero il quesito risolto, pertanto questa sera correggo il titolo aggiungendo [Risolto] anche se la discussione va avanti di parecchi post ;)
Si avevi ragione ci sono capitoli .0 pertanto occorre cercare [0-9]
Io stavo a pensare al numero 10 :-)
No il dieci funzionava, ma non funzionava lo zero
Non so cosa avevo visto, ma anche per logica [1-9][1-9] non può funzionare, tuttalpiù [1-9][0-9] :-[
E quello che dicevo, in pratica, era che un capturing group tipo
Lo leggo come Un numero tra 0 e 9 oppure un numero tra 0 e 9, quindi basterebbe ([0-9])
E ancora
Starebbe a dire due numeri (da 10 a 99) oppure un numero, da 0 a 9. Potrebbe essere ridotto a ([0-9]{1,2})
Ti basta provare questo codice per vedere che non funziona
Public Sub Main()
Dim value As String = "pippo19pluto"
If RegExp.Match(value, "([0-9]{1,2})") Then
Print "MATCH"
value = RegExp.Replace(value, "([0-9]{1,2})", " k&1 ")
Endif
value = Scan(value, "* * *")[1]
Print value
End
Credo che sia per via del fatto che per funzionare deve prima valutare due cifre oppure una cifra e non viceversa...
:ciao:
Non discuto l'espressione, ma se puo' essere accorciata o resa piu' leggibile. Inoltre, se avevo un piano di usare Gambas con le pcre, sarei curioso di sapere come mai il canonico segno della ripetizione non funziona: se vado sui siti di debug online, vedo che va bene invece. Se mi sono spiegato :-)
Anche io vorrei capire come accorciare l'espressione è che non riesco a comprendere cosa mi stai dicendo, puoi essere più chiaro e specifico.
Voglio dire ad esempio come ha fatto bb in questa discussione (https://lists.gambas-basic.org/pipermail/user/2022-January/075084.html), mi ha chiesto : se voglio usare più opzioni di separatori faccio così?
"(([0-9]{1,2}))[/-.]([a-zA-Z]{3,10})[/-.]([0-9]{2,4})"
Io ho capito e gli ho risposto, credo che si faccia cosà
"(([0-9]{1,2}))(/|-|.)([a-zA-Z]{3,10})(/|-|.)([0-9]{2,4})")
:ciao:
Se e' soltanto per riconoscere se e' una data, non occorrono le parentesi se non per dividere le alternative. Le parentesi normalmente servono per le sostituzioni, ma se non ho capito male li' non servono, e basta soddisfare il MATCH. Quella riga, per esempio, a me risulterebbe essere
[0-9]{1,2}[\.-\/]([0-9]{1,2}|[a-zA-Z]{3,9})[\.-\/][0-9]{1,4}
e prende tutte e tre le date che nel messaggio della mailing list mostra come esempi. I separatori potrebbero essere scritti tutti in fila, ".-/", pero' poiche' forse (regex101 mi dice cosi') vanno escapati metto il backslash davanti al punto e allo slash.
ps: non so se sono necessari piccoli accomodamenti, li provo online nella versione PCRE che dovrebbe derivare quella usata da Gambas che qui non ce l'ho installato.
edit: se uso il segno di meno come separatore, pare debba escapare pure quello, e quindi non so se a quel punto convenga fare i separatori come ho fatto io e non come li avevi, dovrei trovare la regola comunemente usata...