Regex

Status
Niet open voor verdere reacties.

The Mighty Atom

Terugkerende gebruiker
Lid geworden
22 mei 2008
Berichten
1.380
Zijn er hier slimmeriken die verstand hebben van reguliere expressies?
Ik moet namelijk een regex hebben voor een bepaalde... regel, maar ik heb gewoon geen idee wat nou de juiste regex pattern daarvoor is...

Ik heb een programma gedownload dat beweert dat het werken met regex makkelijk word als je dat programma gebruikt maar tot nu toe is het me nog steeds niet duidelijk welke rules ik nou moet toepassen om het gewenste resultaat te krijgen zeg maar.

Hier is een voorbeeld string waar ik op wil controleren:

Code:
[B]+0~GENERIC86			255 64 125 10000[/B]


+0~GENERIC86:
Een string met de volgende regex rules:
- Letters van a tot z toestaan
- Letters van A tot Z toestaan
- Getallen 0 tot 9 toestaan
- De chars + ~ _ ! zijn optioneel, ze mogen voorkomen, maar hoeft niet
- Geen enkele whitespace (spatie en/of tabspace) toestaan

Daarna een whitespace. Deze whitespace moet minimaal 1 spatie zijn maar mag ook een combinatie zijn van meerdere spaties en meerdere tab spaces.

255:
Een range van 0 tot 255, minimaal 1 digit, maximaal 3 digits
Daarna volgt 1 whitespace van een spatie (geen tab space)

64:
Zelfde als de 255

125:
Zelfde alse 255 en 64

10000
Zelfde als hierboven met als enigste verschil dat deze integer meerdere digits kan hebben maar wel minimaar 1 digit moet beslaan. Uiteraard mag deze integer wel boven de 255 uitkomen

Dat was alles. Hier zijn nog wat meer example:

Code:
[I]+0~GENERIC65		                                	255 255 255 750
GENERIC87A		                    	100 255 100 1000
GEN_VEND1		                    	50 180 50 1000
EMERGLIGHT			255 200 100 50000
+0~FIFTS_LGHT01		                    	160 170 220 4000
SKKYLITE			                    165 230 255 1000
+0~DRKMTLS1			205 0 0 6000
+0~DRKMTLGT1	                    		200 200 180 6000
+0~DRKMTLS2		                    	150 120 20 30000
+0~DRKMTLS2C			255 200 100 50000
!TOXICGRN		                    	0 255 0 150
!RADIO		                    		0 255 0 100
!toxic				80 150 170 200
+0~light7a	                    		0 255 80 12000[/I]


Ik zou het echt tof vinden als iemand dit zou kunnen uitvogelen, want ik heb hier echt moeite mee. Dat betekend niet dat ik lazy ben, ik ben hier al enkele dagen mee aan het klieren en ik krijg het gewoon niet goed. Heel frustrerend. :(
 
Laatst bewerkt:
Ik ben n.a.v. jouw vraag hier en hier gaan kijken wat het precies is.
Ik begrijp nu dat regex een soort veredelde wildcards techniek is maar dan met veel meer mogelijkheden dan alleen wildcards.

Maar ik snap eerlijk gezegd weinig van de door jou zelf aangedragen voorbeelden.

Ik zou zeggen leg eens in functionele termen uit wat je precies wilt bereiken.
Dan kan ik daarna allicht een poging doen om dat naast die tutorial te leggen achter die 2e link.
 
Ok, ik zal proberen het wat duidelijker uit te leggen, maar dat doe ik morgen, ik heb bezoek hier en die gozer die hiernaast haalt me uit mn concentratie.

Ik zou zeggen, hou deze post in de gaten.

Tof dat je een poging wilt wagen dit voor mij op te lossen.

Btw het programma dat ik heb gebruikt heet RegexBuddy.
 
Kijk eens of het zo kan/klopt:
^[a-zA-Z0-9\+\~\_\!]+*[ ~t]+*[0-9]+*[ ][0-9]+*[ ][0-9]+*$

Hiermee dwing ik (helaas) niet af dat de eerste twee getallen max. 3 posities mogen zijn, maar kijk/test even of dit minstens 90% van de gevallen dekt.
PS: Er staat een spatie vóór de ~t tussen die vierkante haken en er staan 1 spatie in de 'lege' vierkante haken.

Wellicht kan ik het nog verbeteren, maar test even of dit (ong.) doet wat je wilt.

Tijs.
 
Ah, tof van je dat je ook een poging waagt, maar ik krijg ik een error:

bezig met het parseren van "^[a-zA-Z0-9\+\~\_\!]+*[ ~t]+*[0-9]+*[ ][0-9]+*[ ][0-9]+*$" - Niet-herkende escape-tekenreeks \_.

Dit is de code die ik gebruik om mee te testen:

Code:
        If Regex.IsMatch(TextBox1.Text, "^[a-zA-Z0-9\+\~\_\!]+*[ ~t]+*[0-9]+*[ ][0-9]+*[ ][0-9]+*$") Then
            Panel1.BackColor = Color.FromArgb(192, 255, 192) 'Groen, goed
        Else
            Panel1.BackColor = Color.FromArgb(255, 192, 192) 'Rood, fout
        End If

Ik moet steeds even een duidelijkere beschrijving geven van datgene waar ik een regex voor wil hebben, maar dat kost tijd, maar het komt wel.
 
Laatst bewerkt:
"bezig met het parseren van "^[a-zA-Z0-9\+\~\_\!]+*[ ~t]+*[0-9]+*[ ][0-9]+*[ ][0-9]+*$" - Niet-herkende escape-tekenreeks \_."

Beetje raar, want met een '\' escape je tekens (zoals de + en ~ die een speciale functie hebben in regular expressies). Had dus óók voor een '_' gebruikt moeten kunnen worden, maar je kunt natuurlijk kijken wat er gebeurt als je het opzet zónder het escape-karakter '\' ervoor.

Wordt dan dus (met het _ teken iets naar voren geplaatst, zodat de geescapete tekens achteraan de klasse komen staan):
^[a-zA-Z0-9_\+\~\!]+*[ ~t]+*[0-9]+*[ ][0-9]+*[ ][0-9]+*$

Wellicht geeft ie dan weer een foutmelding over "Niet-herkende escape-tekenreeks \!."
Dan kun je het '!'-teken unescapen. Het wordt dan:
^[a-zA-Z0-9_!\+\~]+*[ ~t]+*[0-9]+*[ ][0-9]+*[ ][0-9]+*$

Succes,

Tijs.
 
Laatst bewerkt:
Ik krijg nou een iets andere fout:

bezig met het parseren van "^[a-zA-Z0-9_!\+\~]+*[ ~t]+*[0-9]+*[ ][0-9]+*[ ][0-9]+*$" - Geneste kwantiteitsmeter *.

Wut? Wat is nou weer een kwantiteitsmeter, laat staan een escape teken?
Maar misschien helpt als ik later vanvond die duidelijkere uitleg heb gepost over de string waar ik op wil controleren, misschien dat het dan voor jouw makkelijker wordt om een goede syntax te maken daar voor. :thumb:


Maar echt, wat een gehannes is dit zeg, vind je niet?
 
In het programma waar ik regular expressions gebruik (MicroEmacs programmeerbare editor) is datgene wat ik aangaf 100% werkend.

In de link van evertVB wordt echter een ander escape characters gebruikt, namelijk % ipv. \ en een tab word daar niet voorgesteld als ~t maar als \t
Dat zou verklaren waarom je met mijn regexp een foutmelding kreeg bij het escapen etc.

Hierop aangepast wordt het dan (met het niet meer gebruiken van het *-teken, die ik hoogstwaarschijnlijk verkeerd had gebruikt):
^[a-zA-Z0-9%+%~%_%!]+[ \t]+[0-9]+[ ][0-9]+[ ][0-9]+$

Succes,

Tijs.
 
Ah, nu geen error, maar alle test strings returnen False, dus de regex is fout.

Ik heb een willekeurige string uitgezocht en deze ingedeeld in verschillende gekleurde secties die allen hun eigen regex rules hebben:

string_sections.png


Het grijze deel stelt een string voor waarin alle letters in voor mogen komen, zowel kleine letters als hoofdletters. Daarnaast mogen er ook getallen in voorkomen, 0 t/m 9, en verder mogen de volende characters er ook in voorkomen hoewel deze optioneel zijn, omdat ze niet in elke string voorkomen:

  • Uitroepteken ( ! )
  • Underscore ( _ )
  • Tilde ( ~ )
  • Plus ( + )
  • Min/dash ( - )

De volgende sectie in de string (lichtblauw/cyan) is een whitespace. Deze whitespace moet minsters bestaan uit 1 simpele spatie OF 1 tabspace. Een combinatie van die twee mag ook (tabspace-tabspace-spatie-tabspace-spatie-spatie-spatie-tabspace bijvoorbeeld), zolang het maar 1 type whitespace is.

De derde sectie (rood) is simpel. Als je bekend bent met RGB kleur waarden begrijp je denk ik direct wat deze integer moet voorstellen. Deze integer is dus voor de hoeveelheid rood voor een kleur. Kan bestaan uit 1 digit, 2 digits of 3 digits, waarvan de eerste digit een range heeft van 0 t/m 2, de tweede en derde digits hebben een range van 0 t/m 9. De minimale waarde van deze integer moet 0 zijn en de maximale waarde moet 255 zijn. 256 mag dus niet.

De volgende sectie (paars) is ook simpel. Dit is simpelweg 1 whitespace van een spatie, een tabspace mag niet, maar meerdere spaties mag wel.

De groene sectie heeft zoals je misschien al begrepen hebt dezelfde rules als de rode sectie.

Dan volgt weer een paarse sectie, ook hier geldt dezelfde rule als bij de voorgaande paarse sectie.

Dan volgt blauw. Ook hier geldt dezelfde rule als bij de rode en de groene secties.

Dan de laatste paarse sectie. Zie voorgaande paarse secties.

De laatste sectie (geel) lijkt op de rode, groene en blauwe secties met als grote verschil dat deze integer geen maximum waarde heeft, maar nog wel een minimale waarde van 0, en minstens 1 digit lang moet zijn. Wat betreft de range geldt hier gewoon 0 t/m 9.

En dat was het. Beter dan dat kan ik het niet uitleggen, dus hopelijk hebben jij en evertVB nu een duidelijk idee van wat de bedoeling is :)

:thumb:
 
Laatst bewerkt:
Helaas heb ik geen beter alternatieve regexp voor je. Hopelijk kan evertVB nog met wat komen.

Tijs.
 
Toch nog een andere versie, gebaseerd op dat er blijkbaar in de paarse stukken meerdere spaties mogen staan. Dat is namelijk niet wat je in je originele posting schreef, waar maar 1 spatie was aangegeven.

^[a-zA-Z0-9%+%~%_%!]+[ \t]+[0-9]+[ ]+[0-9]+[ ]+[0-9]+$
 
Ik heb verder geen antwoorden over de programmatuur die je gebruikt. Ik denk dat je daar Google voor moet (gaan) gebruiken.

Tijs.
 
Lijkt erop dat ik 'een cijferreeks vergeten' ben (de laatste op de regel). ;)
Er moet dus nog een [ ]+[0-9]+ bij.
Wordt dan dus:
^[a-zA-Z0-9%+%~%_%!]+[ \t]+[0-9]+[ ]+[0-9]+[ ]+[0-9]+[ ]+[0-9]+$

Succes,

Tijs.
 
Ja die werkt, tenminste, als ik de ^ aan het begin van de regex string en de $ aan het eind weghaal. :D

Maar ik zie toch nog een klein foutje:

Hij returned ook true als de waarde voor R, G en/of B 256 of hoger is, terwijl dat niet eens kan, de maximum moet 255 zijn.
Zie screenshot:

http://www.themightyatom.nl/screenshots/regexbuddy_almostmatch.jpg

Die laatste test string, die begint met _Argh heeft als waarde voor de kleur groen 256. Dat is niet goed. Deze string zou dus false moeten returnen omdat RGB waarden maar tot en met 255 gaan.
 
Kijk, mijn regexp test verder op helemaal niets. Als ik eerlijk mag zijn had ik van je verwacht dat je zélf zou gaan kijken hoe het te finetunen en of wat je wilt eigenlijk wel kan.

Vooral zaken zoals "De derde sectie (rood) is simpel. Als je bekend bent met RGB kleur waarden begrijp je denk ik direct wat deze integer moet voorstellen. Deze integer is dus voor de hoeveelheid rood voor een kleur. Kan bestaan uit 1 digit, 2 digits of 3 digits, waarvan de eerste digit een range heeft van 0 t/m 2, de tweede en derde digits hebben een range van 0 t/m 9. De minimale waarde van deze integer moet 0 zijn en de maximale waarde moet 255 zijn. 256 mag dus niet." zijn niet gemakkelijk in een regexp te vangen.

Ik richt me nu alleen nog op die derde sectie, en dan zul je de evt. beperkingen van de overige 3 getallen die daar achteraan komen zelf moeten uitzoeken:

^[a-zA-Z0-9%+%~%_%!]+[ \t]+([0-1][0-9][0-9]|[2][0-5][0-9]|[0-9][0-9]|[0-9])[ ]+[0-9]+[ ]+[0-9]+[ ]+[0-9]+$

Hiermee heb je nog niet 256, 257, 258 en 259 gedekt, maar het is een begin.

Kijk maar wat dit oplevert.

Tijs.
 
Laatst bewerkt:
Kijk maar wat dit oplevert.

Levert niks op, ik krijg het niet goed.

Waarom kan je niet gewoon zo doen:

[0-255] = een range van 0 t/m 255

Of zoiets.
Dit is echt lastig.

En geloof mij, ik zit al de hele dag te prutsen dit goed te krijgen terwijl ik de reacties afwacht.
Er zijn toch ook regexen om een IP address te matchen? Die gaan ook van 0 t/m 255. Dus ik kan me niet voorstellen dat zoiets niet zou werken bij een RGB values die ook een range hebben van 0-255. Dus dit moet toch te doen zijn lijkt me. Ik ga zoeken naar een regex voor een IP address en kijken of ik dat ene stukje eruit kan halen.

RegexBuddy komt met een hele waslijst aan regexen om direct te gebruiken in je source code, daar zal vast wel ook een regex voor een IP adres tussen zetten.
En ja hoor. :)

Code:
^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$

Ik ga verder prutsen en kijken wat die regex precies doet.

Hoofdpijn = True :confused:
 
Laatst bewerkt:
Dat is juist de grap van het verhaal (ik had al een paar waarschuwingen gegeven): Het meeste is 'karakter'/positie/'woord'-gebaseerd, dus bepaald niet 'getalsmatig'.
Vandaar dat ik al zei dat je het met een regexp oplossing niet eenvoudig maakt voor jezelf.

Persoonlijk zou ik alle checks uitvoeren in een programmeertaal, niet in regular expressies. Dus evt. regular expressies gebruiken voor de eerste selectie/scheiding en dan de secties van 'goedgekeurde' regels in variabelen inlezen en valideren.

Ik zie (bijv.) geen simpele oplossing in regular expressions voor de 'foute' waarden 256, 257, 258 en 259.

Tijs.
 
Ah daar heb je een punt, dat ga dan maar even proberen, maar niet meer vandaag, rofl. :)

Hoe dan ook bedankt voor je hulp. :thumb:
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan