Toon posts:

[REGEXP] Conditioneel vervangen string

Pagina: 1
Acties:
  • 118 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Een reguliere expressie-vraag waar ik niet uitkom:

Ik wil mbv reguliere expressies een string aanpassen, bijvoorbeeld de volgende string:

code:
1
IK WIL FIETSEN EN LOPEN, MAAR NU GAAT DAT NIET EN MORGEN OOK NIET


Nu wil ik alle spaties vervangen door een hekje ('#'), tenzij die spaties een of meer bepaald(e) woord(en) omvatten. Stel dat die woorden 'NU' en 'EN' zijn.

Het resultaat van de vervanging zou dan dus worden:

code:
1
IK#WIL#FIETSEN EN LOPEN,#MAAR NU GAAT#DAT#NIET EN MORGEN#OOK#NIET


Heeft iemand enig idee hoe ik dit aan kan pakken (met Perl-style RegExp-structuur)??

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 07-05 12:23

chem

Reist de wereld rond

Waarom geen explode (of split) ?
Goede kans dat het nog sneller is ook.

Klaar voor een nieuwe uitdaging.


Verwijderd

Topicstarter
chem schreef op maandag 02 mei 2005 @ 22:16:
Waarom geen explode (of split) ?
Goede kans dat het nog sneller is ook.
Omdat het onderdeel is van een aantal bewerkingen die ik in één keer door preg_replace (php) wil laten uitvoeren. Het eerste en tweede argument in
code:
1
preg_replace($search,$replace,$string)

zijn dan arrays met daarin verschillende uit te voeren vervangingen. De hierboven door mij beschreven vervanging is dus één van meerdere.

Nog even los van of het ook anders kan, vast wel, zou ik toch graag willen weten hoe dit op te lossen is met regexps.

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 07-05 12:23

chem

Reist de wereld rond

hmmm...
dan zou ik het proberen met óf een /e, óf met 2 regexps; eerst \s -> #, dan #(woord1|woord2)# -> ' \1 '

Laatste is natuurlijk behoorlijk foutgevoelig als de # ook voor kan komen in de string.

Klaar voor een nieuwe uitdaging.


  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 17-02 19:31
euh...

wat tipjes:

maak een hoop gebruik van subgroepen () dus...

maak gebruik van \w voor woorden....... delimited door spaties

dan krijg je iets van s/(\ *)(\w EN \w)(\ *)/#\2#/

eh. nee gaat ook niet helemaal vlot komen :P

maar iets in die richting moet vast helpen.....

  • esf
  • Registratie: Juni 2002
  • Laatst online: 11-03 14:06

esf

Misschien iets van:
s/(woord1|woord2|woord3){0}( )(woord1|woord2|woord3){0}/#

(Zoek naar spaties waar geen woord1, woord2 of woord3 omheen staat. Ziet er redelijk uit maar ik weet niet precies hoe het met 'niet voorkomen' in regexps werkt.)

[ Voor 9% gewijzigd door esf op 02-05-2005 22:56 ]

The hardest thing in the world to understand is the income tax. - Albert Einstein


Verwijderd

Is dat niet heel erg simpel :?

Vervang alle spaties door #

en vervang dan #en# door spatie_en_spatie
en vervang alle #nu# door spatie_nu_spatie

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
In een regex met lookbehind en lookahead:

Perl:
1
2
3
4
5
6
7
8
#!/usr/bin/perl
#
use strict;

my $l_inp = "IK WIL FIETSEN EN LOPEN, MAAR NU GAAT DAT NIET EN MORGEN OOK NIET";

$l_inp =~ s/ (?<!\b(EN|NU)\b )(?!\b(EN|NU)\b)/#/g;
print $l_inp;


Text output:
1
2
jvs@moniserv:~> ./bla.pl
IK#WIL#FIETSEN EN LOPEN,#MAAR NU GAAT#DAT#NIET EN MORGEN#OOK#NIET

[ Voor 11% gewijzigd door Glimi op 02-05-2005 23:23 . Reden: Even wat bijschaven ]


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Oja, wel even de opmerking erbij dat we dit eigenljik niet meer regulier kunnen noemen omdat het geen Context vrije constructie is.

Verwijderd

Topicstarter
Glimi schreef op dinsdag 03 mei 2005 @ 09:01:
Oja, wel even de opmerking erbij dat we dit eigenljik niet meer regulier kunnen noemen omdat het geen Context vrije constructie is.
Bedankt Glimi, dit is precies wat ik wilde hebben en het werkt goed :). Wat bedoel je met bovenstaande opmerking?
(ps.: nog nooit van lookbehind en lookahead gehoord, toch maar eens wat dieper induiken)

EDIT: hm, dit lijkt helaas alleen te werken met woorden van gelijke lengtes. Je kunt niet de woorden 'EN' en 'OOK' gebruiken, want dat zegt Perl "Variable length lookbehind not implemented in regex; marked by (.....)" en PHP "Compilation failed: lookbehind assertion is not fixed length at offset (.....)"

EDIT2: voor de volledigheid: PHP blijkt af te wijken van de Perl 5.005-standaarden, in die zin dat je wél kunt afwijken van de eis dat lookbehind strings gelijke lengtes moeten hebben, mits je aan bepaalde eisen voldoet. Deze eisen staan vermeld op http://docs.php.net/en/re...gexp.reference.assertions.
Je kunt dan de php-code herschrijven tot
code:
1
2
3
4
5
$str = "IK WIL FIETSEN EN LOPEN, MAAR NU GAAT DAT NIET EN MORGEN OOK NIET";
$search = '/\s(?<!\bEN\b\s|\bOOK\b\s)(?!\b(EN|OOK)\b)/';
$replace = '#';

$str = preg_replace($search,$replace,$str);
waarbij duidelijk is dat er geen 'single top-level branch' (zie link naar docs.php.net) mag zijn, daarom is voluit '\bEN\b\s|\bOOK\b\s' geschreven

[ Voor 74% gewijzigd door Verwijderd op 03-05-2005 10:01 ]


Verwijderd

dit werkt voor alle lengte woorden:

code:
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl
#
use strict;

my $l_inp = "IK WIL FIETSEN EN LOPEN, MAAR NU GAAT DAT NIET EN MORGEN OOK NIET";

$l_inp =~ s/ /#/g;
$l_inp =~ s/#en# / en /g;
$l_inp =~ s/#ook# / ook /g;

print $l_inp;

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 03 mei 2005 @ 10:00:
dit werkt voor alle lengte woorden:
<knip>
Ik weet het, waarom moeilijk doen als....., maar daar gaat het nu even niet om. Aangezien het niet lukte wilde ik perse weten of en hoe het wél op te lossen was met reguliere expressies. En het blijkt dus mogelijk te zijn.

Verwijderd

np...ik dacht dat het je om de oplossing ging.

Ik heb geen idee wat een regulieren expressie is, en ik heb geen enkele ervaring met Perl. Ik kon me alleen bedenken hoe je het oplost, en vervolgens doet Google wonderen :)

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Verwijderd schreef op dinsdag 03 mei 2005 @ 09:17:
Bedankt Glimi, dit is precies wat ik wilde hebben en het werkt goed :). Wat bedoel je met bovenstaande opmerking?
(ps.: nog nooit van lookbehind en lookahead gehoord, toch maar eens wat dieper induiken)
Ik bedoel dat de productieregel (herschrijven van de spatie) afhankelijk is van de context. Dan zit je niet langer meer in de context vrije talen te werken. Aangezien reguliere talen een subset van context vrije talen zijn en reguliere expressies orgineel een uitdrukking waren van reguliere talen, was dit vrij lastig om te vangen in een 'standaard' reguliere expressie. Echter met alle perl trucs is het toch wel te doen.
EDIT: hm, dit lijkt helaas alleen te werken met woorden van gelijke lengtes. Je kunt niet de woorden 'EN' en 'OOK' gebruiken, want dat zegt Perl "Variable length lookbehind not implemented in regex; marked by (.....)" en PHP "Compilation failed: lookbehind assertion is not fixed length at offset (.....)"
Ik ken look-aheads en look-behinds ook pas sinds ik dit heb proberen te implementeren, dus dat wist ik niet :+.
Pagina: 1