[PHP] Teksts uitlezen per keyword

Pagina: 1
Acties:

Onderwerpen


Verwijderd

Topicstarter
Ik heb een groot aantal bestanden met javadoc-style comments. Ik wil deze doorlopen en de file-info (bovenaan elk bestand) in een array stoppen. Hiertoe heb ik nu de volgende functie:
PHP:
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
29
30
31
32
33
34
35
36
<?php

$data = "
/**
 * @file
 *
 * Artikelen zijn stories, voornamelijk gebruikt als nieuwsberichten, die
 * automatisch geplaatst en verwijderd kunnen worden.
 *
 * @author  tweakerert <twe@kerert.nl>
 * @version 0:07 30-12-2009
 */
";

function module_info($data) {
  $return = array();

  preg_match('/@file(.*)/i', $data, $file);
  preg_match('/@author(.*)/i', $data, $author);
  preg_match('/@version(.*)/i', $data, $version);

  $file    = trim(preg_replace('/\r?\n *\* */', ' ', $file[1]));
  $author  = trim($author[1]);
  $version = trim($version[1]); 
  
  if (isset($file) && isset($author) && isset($version)) {
    $return[] = array(
      'author' => $author, 
      'file' => $file, 
      'version' => $version
    );
  }
  return $return;
}

print_r(module_info($data));

Een aantal opmerkingen / vragen:
  • waar @author en @version goed worden uitgelezen, gebeurt dit niet met @file (de array is hier leeg). Kan iemand mij uitleggen wat er verkeerd is aan de gebruikte regex? Ik denk dat het te maken heeft met dat de info achter @file over meerdere regels kan lopen. Hoe houd ik hier rekening mee?
  • ik moet deze functie telkens aanpassen als er andere keywords (naast @file, @author en @version), zoals @todo, @example en @license gebruikt gaan worden. Is het niet mogelijk om generieke functie te schrijven die $data uitleest op al deze keywords en rekening houd met het feit dat informatie over meerdere regels kan lopen en dus newlines kan bevatten?

  • ErikKo
  • Registratie: Mei 2009
  • Laatst online: 08:41

ErikKo

Rippie

Ik heb er even vlug overheen gekeken.
De reden dat @file leeg is omdat de regex de tekst achter @file pakt. Niets dus.
Ik denk dat je een regex moet maken die alle regels, excl. het sterretje, meeneemt totdat hij een nieuwe 'tag' tegenkomt. Alleen op die manier kun je @file een variabel aantal regels geven. En vergeet niet lege regels weg te laten. Trimmen is ook belangrijk, omdat je anders regels met spaties krijgt.

Aangezien de tags universeel zijn, kun je hier misschien zelf een array van maken, en de hele code uitvoeren over een loopje van de array met alle tags erin. Lijkt me iets dynamischer en voorkomt redundante code.

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Die @file over meerdere regels is natuurlijk niet echt een goed voorbeeld van iets dat je met regular expressions zou oplossen, domweg omdat alles een context heeft. De eenvoudigste workaround is het aanpassen van je regexp zodat hij scant tot aan het volgende @-teken, wat niet waterdicht is aangezien je eigenlijk zelfs een lookahead nodig hebt om te kijken of de tekenreeks daarachter wel een valide tag is.

In het kort: kijk eens naar http://php.net/manual/en/...cre.pattern.modifiers.php en dan met name de DOTALL-modifier. Als je echter je regexp op regel 18 verandert in het volgende, dan heb je die niet nodig:
PHP:
18
preg_match('/@file([^@]+)/i', $data, $file);

Maar, zoals ik al zei: waterdicht is dat niet en het is aan jou om te bepalen of dat bruikbaar is of niet. :)

'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!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Dan is het nog makkelijk om achter je /i je de /s modifier te plakken.
PHP:
1
preg_match('/@file(.*)/is', $data, $file);

Dan zal die $data als 1 regel beschouwen, alleen moet je wel oppassen dat hij dan alles pakt omdat je achter (.*) geen einde heeft zoals NMe al opmerkte.

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 10:00
Je zou ook kunnen kijken naar PHP documentor. Wellicht doet dat al gewoon wat je wil, maar als dat niet het geval is kun je in de source ongetwijfeld wat nuttig tips en trucs vinden om je probleem op te lossen.

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • maurad3r
  • Registratie: Oktober 2004
  • Laatst online: 01-09 08:10
Het Zend Framework heeft hier Zend_Reflection voor. Deze heeft ondersteuning voor deze docblocks. Wellicht is dat een betere oplossing?

Acties:
  • 0 Henk 'm!

  • mocean
  • Registratie: November 2000
  • Laatst online: 04-09 10:34
NMe schreef op vrijdag 01 januari 2010 @ 02:11:
...
PHP:
18
preg_match('/@file([^@]+)/i', $data, $file);

Maar, zoals ik al zei: waterdicht is dat niet en het is aan jou om te bepalen of dat bruikbaar is of niet. :)
Ik zie met die @'s al een probleem met e-mail adressen, dan gaat ie dus stoppen bij de @ in het e-mailadres (als ik het juist heb). Je zou ook kunnen zoeken naar "* @", maar ook dat lijkt me foutgevoelig. Makkelijkste lijkt me als je een lijst kan maken van gereserveerde keywords.

Koop of verkoop je webshop: ecquisition.com


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Vandaar ook dat ik lookaheads noem. ;)

'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.

Pagina: 1