[PHP] Regexp aanpassen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Mijn CMS'je bestaat, afhankelijk van de wensen van de klant, uit een aantal modules. Elke module begint als volgt:
PHP:
1
2
3
4
5
/**
 * Module Name: Story
 * Description: Gets a story from the database
 * Version    : 1.2
 */

Ik ben nu bezig met een script wat automatisch door de modules/ directory browsed, en een overzicht maakt van alle geinstalleerde modules:
PHP:
1
2
3
4
5
6
7
8
9
10
11
foreach ($list as $key => $module)
{
  $data = implode('', file(BASE_PATH.'/modules/'.$module.'.module'));

  preg_match("|Module Name:(.*)|i", $data, $module_name);
  preg_match("|Description:(.*)|i", $data, $description);
  preg_match("|Version    :(.*)|i", $data, $version);
    
  if (isset($module_name[1]) && isset($description[1]) && isset($version[1]))
    echo $module_name[1] // etc...
  }

Het nadeel hierbij is dat de Description altijd op 1 regel moet staan, anders pikt de regexp alleen het deel wat direct achter Description staat op. Ik probeer nu een manier te verzinnen waarop ik een beschrijving die over meerdere regels loopt, in zijn geheel kan afvangen:
PHP:
1
2
3
4
5
6
7
8
/**
 * Module Name: Story
 * Description: This module grabs a story from
 *              the database, then parses it to
 *              some function, which outputs
 *              the formatted text to the client
 * Version    : 1.2
 */

Mijn huidige functie retourneert in dit geval $description[1] = 'This module grabs a story from'. Wie heeft een idee om hier verder me te komen?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • JayVee
  • Registratie: Mei 2002
  • Laatst online: 31-08 10:22

JayVee

shibby++!

Je moet zorgen dat meerdere line breaks meegenomen worden. Die kan je dan met str_replace omzetten in <br> als je dat wil.
PHP:
1
preg_match("|Description:([.\n\r]*)|i", $data, $description);
?
Om ervoor te zorgen dat hij Version niet meepakt moet je die char group misschien anders schrijven.
PHP:
1
[\w\d\s\n\r]*
misschien? Ik ben redelijk n00b met RegExps

ASCII stupid question, get a stupid ANSI!


Acties:
  • 0 Henk 'm!

  • MarkvE
  • Registratie: Maart 2004
  • Laatst online: 30-01 17:16
Gebruik naast de i modifier ook de m modifier.

[ Voor 4% gewijzigd door MarkvE op 05-01-2005 16:01 ]

Vormkracht10


Acties:
  • 0 Henk 'm!

  • RedRose
  • Registratie: Juni 2001
  • Niet online

RedRose

Icebear

PHP:
1
preg_match('|Description: (.*?)\* Version|im',blaaa);


ofzo?

[ Voor 15% gewijzigd door RedRose op 05-01-2005 16:04 . Reden: zo dan he :P ]

Sundown Circus


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
@JayVee, @RedRose - bedankt voor jullie suggesties, maar ze werken niet. Ik had al eerder eenzelfde oplossing geprobeerd als RedRose, maar ook die was niet succesvol. Wellicht heeft iemand nog een ander idee?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • RedRose
  • Registratie: Juni 2001
  • Niet online

RedRose

Icebear

Ook de s-modifier gebruiken. :)

Sundown Circus


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Reveller schreef op woensdag 05 januari 2005 @ 16:39:
@JayVee, @RedRose - bedankt voor jullie suggesties, maar ze werken niet. Ik had al eerder eenzelfde oplossing geprobeerd als RedRose, maar ook die was niet succesvol. Wellicht heeft iemand nog een ander idee?
Definiëer "ze werken niet" eens. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Bedankt, RedRose (en iedereen die ook gereageerd heeft). Ik heb nu het volgende maar zit met een onverwacht probleem - heel dom eigenlijk:
PHP:
1
2
3
4
5
6
7
8
9
10
/**
 * Module Name: Story
 * Description: This module grabs a story from
 *              the database, then parses it to
 *              some function, which outputs
 *              the formatted text to the client
 * Version    : 1.2
 */

preg_match("|Description: (.*?)\* Version|ims", $data, $description);

De output hiervan is: This module grabs a story from* the database, then parses it to* some function, which outputs* the formatted text to the client. Met andere woorden - de asteriksen (*) worden ook meegenomen.

Logisch natuurlijk, maar ik vraag me nu af wat een elegante manier is om die asteriksen er tussenuit te halen. Ik heb nu dit
PHP:
1
str_replace('*', ' ', $description[1])

De output is nu: This module grabs a story fromthe database, then parses it tosome function, which outputsthe formatted text to the client. Het is gek dat de asteriks niet door een spatie wordt vervangen...&nbsp werkt wel maar is niet zo mooi.

Vragen:
• waarom werkt de str_replace niet goed
• heeft iemand een betere oplossing in gedachten (bv. regexp aanpassen?)

@NMe - "ze werken niet": ze geven geen output :) Je hebt gelijk...

[ Voor 31% gewijzigd door Reveller op 05-01-2005 21:11 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

De output bewerken met str_replace lijkt me gunstiger, want de regexp aanpassen kost, als het al mogelijk is, veel meer rekenwerk volgens mij.

Edit: snel je post editen he? :P
Waarom die replace niet werkt weet ik niet. Ziet het in de HTML source ook zo uit?

[ Voor 30% gewijzigd door NMe op 05-01-2005 21:12 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
@NMe - Dat dacht is eigenlijk ook.

Blijft de vraag waarom replacen met ' ' geen spaties geeft. Wellicht heeft het te maken met het resultaat van de regexpen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
/**
 * Module Name: Story
 * Description: This module grabs a story from
 *              the database, then parses it.
 * Version    : 1.2
 */ 

preg_match("|Module Name: (.*)|i"             , $data, $module_name);
preg_match("|Description: (.*?)\* Version|ims", $data, $description);
preg_match("|Version    : (.*)|i"             , $data, $version);

echo $module_name[1].str_replace('*', ' ', $description[1]).$version[1];

Geeft als html-output:
HTML:
1
2
3
Story
This module grabs a story fromthe database, then parses it.
 1.2
Met andere woorden:
• een newline achter $module_name[1]
• een newline achter $description[1] en een spatie voor $version[1]

Terwijl je als output 1 lange string zou verwachten? Er is dus ws. iets verkeerd aan de regexpen maar ik zie niet wat. Iemand wel?

[ Voor 128% gewijzigd door Reveller op 05-01-2005 22:25 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

PHP:
1
2
3
4
5
6
7
$text = "This module grabs a story from
 *              the database, then parses it.
";

$text = preg_replace('/[\s*]+/', ' ', $text);

echo $text;

;)

(waarschijnlijk hou je nog een spatie aan het einde over, maar die kan je met een simpele rtrim() wel wegwerken)

[ Voor 27% gewijzigd door crisp op 05-01-2005 22:59 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • vargo
  • Registratie: Januari 2001
  • Laatst online: 09:35
crisp schreef op woensdag 05 januari 2005 @ 22:57:
PHP:
1
2
3
4
5
6
7
$text = "This module grabs a story from
 *              the database, then parses it.
";

$text = preg_replace('/[\s*]+/', ' ', $text);

echo $text;

;)

(waarschijnlijk hou je nog een spatie aan het einde over, maar die kan je met een simpele rtrim() wel wegwerken)
Moet er ook geen ungreedy modifier bij: /u?
Dit ivm eventueel meerdere '*'s?

[ Voor 8% gewijzigd door vargo op 05-01-2005 23:03 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

vargo schreef op woensdag 05 januari 2005 @ 23:03:
[...]

Moet er ook geen ungreedy modifier bij: /u?
Dit ivm eventueel meerdere '*'s?
Tsja, als er in de description een * staat die bij de tekst hoort dan raak je die nu ook kwijt. Fact is echter dat een ungreedy modifier dat niet gaat oplossen, dan moet je je regels anders specificeren, bijvoorbeeld:
PHP:
1
$text = preg_replace('/\r?\n\s*\*\s+/', ' ', $text);

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik kom er niet uit - hoe schrijf je nu jouw oplossing:
PHP:
1
preg_replace('/[\s*]+/', ' ', $text);
als je hem inpast bij
PHP:
1
preg_match("|Description: (.*?)\* Version|ims", $data, $description);
?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 19-09 22:18

chem

Reist de wereld rond

Iets algemener aanvaard is trouwens de @ hiervoor te gebruiken...

PHP:
1
2
3
4
5
6
7
8
9
10
    /**
    *   returns the error type
    *
    *   @author Schnappi <schnappi@schnappi.tv>
    *   @version 1.3.9
    */
    function get_error()
    {
        return $this->errortype;
    }

Klaar voor een nieuwe uitdaging.


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
chem schreef op donderdag 06 januari 2005 @ 12:29:
Iets algemener aanvaard is trouwens de @ hiervoor te gebruiken...
Dat heb ik ook al vaker gezien ja. Volgens mij komt dit voornamelijk omdat PHPDoc standaard die syntax ondersteunt bij het aanleggen van documentatie - of zit ik er nu naast? Is er nog een andere reden om die notatie aan te houden? Als ik er nu dan toch mee bezig ben, dan het lieft ineens zo standaard mogelijk natuurlijk :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • Wacky
  • Registratie: Januari 2000
  • Laatst online: 05-09 21:19

Wacky

Dr. Lektroluv \o/

code:
1
2
preg_match_all('|Description: (.+?)* Version|',$bron,$doel);
$description = $doel[1][0];


Misschien dat dit wel werkt? :)

Nu ook met Flickr account


Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 16-09 18:38
Reveller schreef op donderdag 06 januari 2005 @ 13:15:
[...]

Dat heb ik ook al vaker gezien ja. Volgens mij komt dit voornamelijk omdat PHPDoc standaard die syntax ondersteunt bij het aanleggen van documentatie - of zit ik er nu naast? Is er nog een andere reden om die notatie aan te houden? Als ik er nu dan toch mee bezig ben, dan het lieft ineens zo standaard mogelijk natuurlijk :)
phpDoc, idd. En ook voor Java, geloof ik. Automatisch documentatie genereren bij je code, wie wil dat niet?

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Dat verandert de zaak wel enigszins. Ik ben zojuist in de documentatie van phpDoc gedoken, en zie dat zij een goede functie beschrijving als volgt zien:
PHP:
1
2
3
4
5
6
7
8
/**
 * De functie doet leuke dingen binnen een nog
 * leukere class
 *
 * @author Reveller
 * @name Story
 * @version 1.0.2
 */

Als ik mijn modules op deze manier beschrijf, zijn ze ook meteen 'phpDoc-ready' :) wanneer ik dat later ga gebruiken (heb er net even mee gespeeld en het werkt ontzettend goed; moet alleen mijn commentaar aanpassen), wordt ineens alles goed geparsed.

De vraag die ik nu wel heb is hoe de regexp eruit moet zien die de beschrijving "De functie doet leuke dingen...") uitleest. Ik heb namelijk geen referentiepunt, zoals ik dat wel bij @author, @name en @version wel heb. Het is wel het eerste commentaar op de pagina, dus misschien kan ik alle zinnen nemen vanaf de eerste /** op de pagina tot aan @author, maar dan moet de volgorde van die documentatie wel altijd gelijk zijn. Ideeen hierover iemand?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
edit:
Een bescheiden * kick * omdat ik er zelf niet uit kom :) Wie heeft een idee voor de regexp die de beschrijving uitleest (zie post hierboven)?

[ Voor 39% gewijzigd door Reveller op 07-01-2005 18:51 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • seamus21
  • Registratie: December 2001
  • Laatst online: 24-02-2018
Even een workaround hoor maar als je nou voor alle description regels @desc zet aangezien je weet hoe je per 1 regel moet filteren. Dan filter je daarna alle @desc eruit met str_replace. Of zit ik helemaal verkeerd te denken?

[ Voor 4% gewijzigd door seamus21 op 08-01-2005 00:06 ]

Always shoot for the moon. Even if you miss you will land among the stars...


Acties:
  • 0 Henk 'm!

  • MarkvE
  • Registratie: Maart 2004
  • Laatst online: 30-01 17:16
Ik krijg het niet met één RegExp gedaan, wel met twee. So this should do the job well...

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

$str = '/**
         * Deze functie doet leuke dingen binnen een nog
         * leukere class.
         *
         * @author Reveller
         * @name Story
         * @version 1.0.2
         */';

preg_match ( '/\/\*\*(.+)@author/is', $str, $match );

$description = trim ( preg_replace ( '/(\r|\n|\*| {1,})+/', ' ', $match [ 1 ] ) );

echo $description;

?>


Een werkend voorbeeld.

[ Voor 46% gewijzigd door MarkvE op 08-01-2005 00:09 ]

Vormkracht10


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

Jouw voorbeeld stripped ook asterisks binnen het commentaar en houd geen rekening met unix-newlines. Ik zou het zo doen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$str = '/**
         * Deze functie doet *leuke* dingen binnen een nog
         * leukere class.
         *
         * @author Reveller
         * @name Story
         * @version 1.0.2
         */';

preg_match ( '/\/\*\*(.+)(?=@author)/is', $str, $match );

$description = trim ( preg_replace ( '/\r?\n *\* */', ' ', $match [1] ) );

echo $description;

;)

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Bedankt iedereen (en voornamelijk crisp)! In principe werkt het nu, maar ik blijf zitten met de linebreaks bij mijn eigen regexpen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$str = '/**
         * Deze functie doet *leuke* dingen binnen een nog
         * leukere class.
         *
         * @author Reveller
         * @name Story
         * @version 1.0.2
         */';

preg_match('/\/\*\*(.+)(?=@author)/is', $str, $match);
preg_match('/@author(.*)/i', $str, $author);
preg_match('/@name(.*)/i', $str, $name);
preg_match('/@version(.*)/i', $str, $version);

$description = trim(preg_replace('/\r?\n *\* */', ' ', $match [1]));

echo '<p>'.$description.'</p>';
echo '<p>'.$author[1].'</p>'; 
echo '<p>'.$name[1].'</p>'; 
echo '<p>'.$version[1].'</p>';

levert de volgende
HTML:
1
2
3
4
<p>Deze functie doet *leuke* dingen binnen een nog leukere class.</p><p> Reveller
</p><p> Story
</p><p> 1.0.2
</p>

Met andere woorden: een break na Reveller, Story en 1.0.2. Weet iemand hoe dit komt?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • MarkvE
  • Registratie: Maart 2004
  • Laatst online: 30-01 17:16
Reveller schreef op zaterdag 08 januari 2005 @ 15:01:
Bedankt iedereen (en voornamelijk crisp)! In principe werkt het nu, maar ik blijf zitten met de linebreaks bij mijn eigen regexpen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$str = '/**
         * Deze functie doet *leuke* dingen binnen een nog
         * leukere class.
         *
         * @author Reveller
         * @name Story
         * @version 1.0.2
         */';

preg_match('/\/\*\*(.+)(?=@author)/is', $str, $match);
preg_match('/@author(.*)/i', $str, $author);
preg_match('/@name(.*)/i', $str, $name);
preg_match('/@version(.*)/i', $str, $version);

$description = trim(preg_replace('/\r?\n *\* */', ' ', $match [1]));

echo '<p>'.$description.'</p>';
echo '<p>'.$author[1].'</p>'; 
echo '<p>'.$name[1].'</p>'; 
echo '<p>'.$version[1].'</p>';

levert de volgende
HTML:
1
2
3
4
<p>Deze functie doet *leuke* dingen binnen een nog leukere class.</p><p> Reveller
</p><p> Story
</p><p> 1.0.2
</p>

Met andere woorden: een break na Reveller, Story en 1.0.2. Weet iemand hoe dit komt?
trim... B)

Vormkracht10


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Dank je! Wat stom ... het stond gewoon voor m'n neus. En ik maar prutsen aan die regexp om het goed te krijgen. Voor iedereen die er nog eens wat aan heeft:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$str = '/**
         * Deze functie doet *leuke* dingen binnen een nog
         * leukere class.
         *
         * @author Reveller
         * @name Story
         * @version 1.0.2
         */';

preg_match('/\/\*\*(.+)(?=@author)/is', $str, $description);
preg_match('/@author(.*)/i', $str, $author);
preg_match('/@name(.*)/i', $str, $name);
preg_match('/@version(.*)/i', $str, $version);

$description = trim(preg_replace('/\r?\n *\* */', ' ', $description[1]));
$author      = trim($author[1]);
$name        = trim($name[1]);
$version     = trim($version[1]);

echo '<p>'.$description.'</p>';
echo '<p>'.$author.'</p>'; 
echo '<p>'.$name.'</p>'; 
echo '<p>'.$version.'</p>';

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."

Pagina: 1