[java] regex quantifiers

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hey,

Ik weet niet hoe het met jullie zit, maar regex expressies gebruiken in java haat ik dus als de pest.
Ik heb er al heel lang over gedaan om onderstaande regex samen te stellen:

Java:
1
"^[A-Z]([a-zA-Z ']|(: ))*$"


En nu moet ik er nog voor zorgen dat een apostrophe, dus het teken ' , maar max 2 keer kan voorkomen. Ik zit dus te kijken naar quantifiers, maar het lijkt maar niet te lukken om het werkend te krijgen. Het lijkt wel alsof hij de quantifier gewoon niet wil nemen. Heb tot nu toe nog geen duidelijk voorbeeld gevonden via google waar dit (quantifiers) goed werd uitgelegd.

Is er hier iemand die mij kan uitleggen hoe zo'n quantifier werkt? Ik krijg het zelfs niet voor elkaar om een simpel voorbeeld uit te werken... :'(

Bij voorbaat dank

Acties:
  • 0 Henk 'm!

  • Grum
  • Registratie: Juni 2001
  • Niet online
De regex matched: "AA: a: : : Aa" en dat ziet er wat raar uit ;)

Wat is de data die je wil matchen? en als je zoekt naar balanced quotes dan is misschien een regex niet echt optimaal.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Grum schreef op vrijdag 14 mei 2010 @ 09:40:
De regex matched: "AA: a: : : Aa" en dat ziet er wat raar uit ;)

Wat is de data die je wil matchen? en als je zoekt naar balanced quotes dan is misschien een regex niet echt optimaal.
Die match is idd toegelaten. Het is de bedoeling om te controleren of een gegeven naam geldig is, de eisen zijn:
-start met hoofdletter
-enkel letters en het dubbele punt en ' zijn toegelaten
-een dubbel punt mag voorkomen maar enkel na een spatie
-een ' mag maximaal 2 keer voorkomen

rare eisen, maar dat is de opgave :)

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 13:46

crisp

Devver

Pixelated

een dubbel punt mag voorkomen maar enkel na een spatie
Je bedoelt "gevolgd door een spatie" neem ik aan?

Verder moet je hier niet denken aan quantifiers, maar aan een herhaling van een submatch minus de apostroph, oftewel iets als:

1) start met een hoofdletter
2) gevolgd door letters, dubbele punt, spatie of apostroph (waarbij dubbele punt altijd gevolgt door een spatie)
3) gevolgd door letters, dubbele punt of spatie (waarbij dubbele punt altijd gevolgt door een spatie)

en dan is het een kwesite om ervoor te zorgen dat 2) doorgaat naar 3) als er een apostroph is gematched :)

Intentionally left blank


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
crisp schreef op vrijdag 14 mei 2010 @ 10:07:
[...]

Je bedoelt "gevolgd door een spatie" neem ik aan?

Verder moet je hier niet denken aan quantifiers, maar aan een herhaling van een submatch minus de apostroph, oftewel iets als:

1) start met een hoofdletter
2) gevolgd door letters, dubbele punt, spatie of apostroph (waarbij dubbele punt altijd gevolgt door een spatie)
3) gevolgd door letters, dubbele punt of spatie (waarbij dubbele punt altijd gevolgt door een spatie)

en dan is het een kwesite om ervoor te zorgen dat 2) doorgaat naar 3) als er een apostroph is gematched :)
Ik bedoelde idd dat een dubbele punt moest gevonden worden door een spatie :)
zal eens kijken naar die herhaling, kwam ik ook ergens tegen in de API :)

Acties:
  • 0 Henk 'm!

  • Salandur
  • Registratie: Mei 2003
  • Laatst online: 14:28

Salandur

Software Engineer

Ik zou dit oplossen met een extra pattern of gewoon tellen hoe vaak een apostroph er in voorkomt door middel van indexOf. Met regular expressions tellen is erg lastig.

Wat je wel kan doen is de suggestie van crisp volgen, waarbij je de herhaling van punt 2 op 2 keer zet door middel van {2}. Het wordt dan zo iets:
Java:
1
"^[A-Z]([a-zA-Z ']|: ){2}([a-zA-Z ]|: )*$"

Assumptions are the mother of all fuck ups | iRacing Profiel


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Salandur schreef op vrijdag 14 mei 2010 @ 13:55:
Het wordt dan zo iets:
Java:
1
"^[A-Z]([a-zA-Z ']|: ){2}([a-zA-Z ]|: )*$"
Gaat niet werken, want dan kan de ' alleen op de eerste 2 posities na de hoofdletter. Zoiets kan wel:
code:
1
^[A-Z](?:[a-zA-Z ]|: )*+(?:'?(?:[a-zA-Z ]|: )*+){2}$


Je kan het ook als een gescheiden conditie zien ((?=(?:[^']*+'?){2}[^']*+$)):
code:
1
^[A-Z](?=(?:[^']*+'?){2}[^']*+$)(?:[a-zA-Z ']|: )*+$


Maar als je regexp's haat, waarom zou je dit niet gewoon uitprogrammeren in java? Een simpele parser die hetzelfde doet is niet zo heel moeilijk lijkt me. Eerst de eerste hoofdletter testen, dan alle letters af, waarbij je bij de : test of er nog een spatie na volgt, en bij de ' test of er niet al te veel geweest zijn. Lijkt me makkelijker teruglezen. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@Salandur en pedorus: bedankt voor alle input :)

En waarom geen regex vraag je?
Wel eerst had ik geen regex, en controleerde ik gewoon via if statements of de naam voldeed. Persoonlijk vind ik dit nogal omslachtig, zeker als er een conditie bijkomt.

en werken met parsers, dat wil dan zeggen dat je niet meer in Java zelf gaat werken? (of je gaat "vreemde" bibliotheken gebruiken?). Dit vermijd ik toch wel liever, ook omdat dat helemaal niet de bedoeling is van het project.

Ik kijk nog wat verder, maar de bovenstaande regexen lijken mij wel bruikbaar (wil ze eerst zelf wel geanalyseerd en gesnapt hebben voordat ik ze implementeer).

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Verwijderd schreef op vrijdag 14 mei 2010 @ 20:44:
Wel eerst had ik geen regex, en controleerde ik gewoon via if statements of de naam voldeed. Persoonlijk vind ik dit nogal omslachtig, zeker als er een conditie bijkomt.
Huh? Dat is juist een stuk eenvoudiger in die situatie volgens mij! :p Ik bedoel dus iets als:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public static boolean isValidName(String name) {
        if (name.isEmpty() || !Character.isUpperCase(name.charAt(0)))
            return false; // must start with uppercase character
        int apostrophes = 0;
        for (int i = 1; i < name.length(); i++) {
            char ch = name.charAt(i);
            if (ch == '\'') {
                if (++apostrophes > 2)
                    return false; // 2 apostrophes max
            } else if (ch == ':') {
                if ((i == name.length() - 1) || name.charAt(i + 1) != ' ')
                    return false; // ':' must be followed by ' '
            } else if (!((ch == ' ') || (Character.isLetter(ch))))
                return false; // only '\'', ':', ' ' and letter allowed
        }
        return true;
    }

Dit staat ook internationale letters toe. Dit zal sneller gaan dan een regexp, en het is imo beter te begrijpen en beter onderhoudbaar.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Bl4ckviper
  • Registratie: Mei 2002
  • Laatst online: 06-08 00:09

Bl4ckviper

BlaBlaBla

Ik gebruik altijd:

http://www.fileformat.info/tool/regex.htm

Om mijn regex-en te testen. Heb ook altijd een hekel aan die dingen..

Be fast .... Be furious....

Pagina: 1