Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

Regular Expressions: Matchen, maar niet 'pakken'

Pagina: 1
Acties:

  • OddesE
  • Registratie: Oktober 2001
  • Laatst online: 18-08-2021
Ik heb een simpele use-case die ik dacht wel even met een regular expression op te lossen, maar tot nu toe kom ik er niet uit. Uitgaande van een string met comma separated values, bijvoorbeeld:

"deze tekst,bevat komma's escaped met backslash,zoals wie\, wat en waar"

Ik wil de tekst splitten op komma's, waarbij komma's escaped met een backslash (de komma na "wie" bijv.) niet mee moeten tellen.

Dus na de split moet er dit uitkomen:

deze tekst
bevat komma's escaped met backslash
zoals wie\, wat en waar

en niet:

deze tekst
bevat komma's escaped met backslash
zoals wie\
wat en waar

Java's String.split pakt een regex als param, dus ik dacht aan zoiets als dit:

[^\\],

oftewel alle komma's die niet vooraf gegaan worden door een backslash.
Dit werkt bijna, er komt dit uit:

deze teks
bevat komma's escaped met backslas
zoals wie\, wat en waar

De laatste letter van alle delen behalve het laatste deel valt weg.
Ik snap waarom, namelijk omdat het eerste deel van mijn regex alle karakters matched behalve de backslash. De 't' aan het eind van 'deze tekst' wordt dus opgevat als deel van het separator symbool.
Wat ik eigenlijk wil is alleen de komma matchen, en dan ook alleen als ie niet vooraf gegaan wordt door een backslash... ik moet dus op de een of andere manier aangeven dat het eerste deel van de expressie geen onderdeel van de match moet worden... maar ik ben helemaal de weg kwijt met greedy en reluctant en possesive quantifiers en caopturing groups e.d... :(

Kan iemand me helpen?

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 21:21

Reptile209

- gers -

Beetje flauw misschien, maar kan je niet voor het splitten alle escaped komma's vervangen door iets anders (bijv. een # als die verder niet in je teksten voor zal komen). Na de split moet je je array nog een keer door om ze weer terug te zetten.

Zo scherp als een voetbal!


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Ik weet dat je dit waarschijnlijk niet wilt horen, maar kun je niet gewoon straightforward door je string heenlopen en splitsen waar nodig?

Dus (m'n java is een beetje roestig, maar in grote lijnen zou 't moeten kloppen) :
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int index = 0;
int startIndex = 0;

List<String> result = new List<String>();

while(index < line.length())
{
    int nextCommaIndex = line.firstIndexOf(index, ',');
    if(nextCommaIndex < 0)
    {
        //No more comma's left in the remainder (if any), store it and exit.
        if(nextCommaIndex < line.length() - 1)
            result.Add(line.subString(startIndex, line.length() - 1));
            
        break;
    }
    
    if(nextCommaIndex > 0 && line.charAt(nextCommaIndex - 1) != '\\')
    {
        //Found a comma without preceding backslash, store range [startIndex, nextCommaIndex)...
        result.Add(line.subString(startIndex, nextCommaIndex));
        
        //...and set the next starting point to just after the comma.
        startIndex = nextCommaIndex + 1;
    }
    
    index = nextCommaIndex + 1;
}

  • writser
  • Registratie: Mei 2000
  • Laatst online: 22:40
Misschien een beetje mierenneuken, maar kunnen er ook gebackslashte backslashes (mooie term :P) in je teksten voorkomen? Bijv:
code:
1
Dit is een backslash: \\, Dit is de volgende regel.

In dat geval is je probleem nog weer ietsje lastiger.

[ Voor 3% gewijzigd door writser op 11-09-2008 21:31 ]

Onvoorstelbaar!


  • OddesE
  • Registratie: Oktober 2001
  • Laatst online: 18-08-2021
Kunnen er ook gebackslashte backslashes (mooie term :P) in je teksten voorkomen?
Ja, maar ik wou niet alle problemen tegelijk oppakken :)

Aan de anderen: Ik snap dat ik er ook 'handmatig' doorheen kan lopen (heb die code zelfs al geschreven) maar het is nu een soort uitdaging geworden. Het moet volgens mij kunnen en dan wil je op een gegeven moment weten hoe het werkt he :)

Overigens denk ik dat het negeren van komma's achter gebackslashte backslashes (ik neem hem over die term :) ) meer van hetzelfde is als ik eenmaal snap hoe ik die eerste komma kan matchen...
Pedorus, kun je het uitleggen alsof ik drie jaar ben? Ik snap ut niet... zoiets als dit dan of zo?

(?<![^\\]),

Ik ga vandaag nog effe proberen. Mocht ik erachter komen zet ik het antwoord hier neer natuurlijk

  • OddesE
  • Registratie: Oktober 2001
  • Laatst online: 18-08-2021
Met dank aan Pedorus, het eerste deel van de oplossing:

code:
1
2
3
4
5
String s = "Text,that,contains commas,escaped with \\\\, cool \\, great and nifty huh?";
System.out.println("text: " + s);
String[] parts = s.split("(?<!\\\\),");
for (String part : parts)
    System.out.println("part: " + part);


output:

code:
1
2
3
4
5
text: Text,that,contains commas,escaped with \\, cool \, great and nifty huh?
part: Text
part: that
part: contains commas
part: escaped with \\, cool \, great and nifty huh?

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
En als je nu \\\ in je text hebt? Dan gaat het zeker weer niet goed.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • pedorus
  • Registratie: Januari 2008
  • Niet online
Uitbreiden naar gebackslashte backslashes is nog niet zo eenvoudig. Ik heb zelfs het vermoeden dat string.split van java dit niet kan, vanwege het niet goed omgaan met groups en het niet aan kunnen van willekeurige terugkijklengtes. Tot 99999*2+1 backslashes gaat het volgende wel goed:
code:
1
(?<=(?:^|[^\\\\])(?:\\\\\\\\){0,99999}),

Maar dat is een workaround natuurlijk. Met matcher kan het wel:
code:
1
((?:[^\\\\,]+|\\\\(?:.|$))*)(?:,|(?<!\\G)$)

Maar dat ziet er eigenlijk ook niet uit. Daarnaast wil je na het splitten vast alsnog gaan unescapen neem ik aan?

Kortom, een echte parser is toch de beste oplossing voor dit probleem. Zo gemaakt met een StringBuilder :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • OddesE
  • Registratie: Oktober 2001
  • Laatst online: 18-08-2021
Ik heb er inderdaad uiteindelijk toch maar mijn eigen parse functie voor geschreven.. Met reguliere expressies werd me toch te ingewikkeld...
Pagina: 1