Question

Voici le deal. Existe-t-il un moyen de faire en sorte que les chaînes soient marquées dans une ligne basée sur plusieurs expressions rationnelles?

Un exemple:

Je dois obtenir tous les tags href, leur texte correspondant et un autre texte basé sur une regex différente. J'ai donc 3 expressions et j'aimerais marquer la ligne et extraire des jetons de texte correspondant à chaque expression.

En fait, j’ai fait cela en utilisant flex (à ne pas confondre avec Adobe), qui est une implémentation du bon vieux Lex. lex fournit une manière élégante de le faire en exécutant des "actions". basé sur des expressions. On peut contrôler le chemin lex lisant aussi un fichier (lecture basée bloc / ligne).

Le problème est que flex produit réellement du code C / C ++ qui effectue le travail de création de jetons. j'ai un faire un fichier qui englobe toutes ces choses. Je me demandais si perl / python pouvait en quelque sorte faire la même chose. C'est juste que j'aimerais tout faire J'aime dans un seul langage de programmation.

La création de jetons n'est que l'une des tâches que je souhaite effectuer dans le cadre de mon application.

Hormis Perl ou Python, tout langage (également fonctionnel) peut-il le faire?

J'ai lu des articles sur PLY et ANTLR ici ( Analyse, où peut J'apprends à ce sujet ).

Mais existe-t-il un moyen de le faire naturellement en python lui-même? excusez mon ignorance, mais ces outils sont-ils utilisés dans des produits / services populaires?

Merci.

Était-ce utile?

La solution

Si vous souhaitez spécifiquement analyser des liens dans des pages Web, WWW de Perl: : Le module Mécaniser vous aidera à comprendre de manière très élégante. Voici un exemple de programme qui saisit la première page de Stack Overflow et analyse tous les liens, en imprimant leur texte et les URL correspondantes:

#!/usr/bin/perl
use strict;
use warnings;
use WWW::Mechanize;

my $mech = WWW::Mechanize->new;

$mech->get("http://stackoverflow.com/");

$mech->success or die "Oh no! Couldn't fetch stackoverflow.com";

foreach my $link ($mech->links) {
    print "* [",$link->text, "] points to ", $link->url, "\n";
}

Dans la boucle principale, chaque $ link est un WWW :: Mechanize :: Link , vous n'êtes donc pas seulement obligé d'obtenir le texte et l'URL.

Tout le meilleur,

Paul

Autres conseils

Consultez la documentation des modules suivants sur CPAN

.

HTML :: TreeBuilder

HTML :: TableExtract

et

Parse :: RecDescent

J'ai utilisé ces modules pour traiter des pages Web assez volumineuses et complexes.

On dirait que vous voulez vraiment analyser le code HTML. Je vous recommande de regarder l'un des merveilleux packages pour le faire:

Ou! Vous pouvez utiliser un analyseur tel que l’un des suivants:

  • PyParsing
  • DParser - Analyseur GLR avec de bonnes liaisons en python.
  • ANTLR - Un générateur d'analyseur récursif décent pouvant générer du code python.

Cet exemple provient de BeautifulSoup Documentation :

from BeautifulSoup import BeautifulSoup, SoupStrainer
import re

links = SoupStrainer('a')
[tag for tag in BeautifulSoup(doc, parseOnlyThese=links)]
# [<a href="http://www.bob.com/">success</a>, 
#  <a href="http://www.bob.com/plasma">experiments</a>, 
#  <a href="http://www.boogabooga.net/">BoogaBooga</a>]

linksToBob = SoupStrainer('a', href=re.compile('bob.com/'))
[tag for tag in BeautifulSoup(doc, parseOnlyThese=linksToBob)]
# [<a href="http://www.bob.com/">success</a>, 
#  <a href="http://www.bob.com/plasma">experiments</a>]

Avez-vous consulté PyParsing ?

À partir de leur page d'accueil:

Voici un programme pour analyser "Bonjour le monde!" (ou toute salutation de la forme ","! "):

from pyparsing import Word, alphas
greet = Word( alphas ) + "," + Word( alphas ) + "!" # <-- grammar defined here
hello = "Hello, World!"
print hello, "->", greet.parseString( hello )

Le programme génère les éléments suivants:

Hello, World! -> ['Hello', ',', 'World', '!']

Si votre problème a quelque chose à voir avec le scraping Web, je vous recommande de regarder Web. :: Racleur , qui permet une sélection facile des éléments via les sélecteurs XPath ou CSS. J'ai un conversation sur le Web :: Scraper , mais si vous utilisez babelfish ou regardez simplement les exemples de code, cela peut vous aider à obtenir un aperçu rapide de la syntaxe.

L'analyse manuelle du langage HTML est onéreuse et ne vous fera pas beaucoup plus que d'utiliser l'un des analyseurs HTML prédéfinis. Si votre code HTML varie très peu, vous pouvez vous débrouiller en utilisant des expressions rationnelles astucieuses, mais si vous êtes déjà en train de décomposer des outils d'analyse syntaxiques de base, vous aurez l'impression que votre code HTML est bien plus régulier que ce qu'il est sain d'analyser. expressions régulières.

De perlop :

  

Un idiome utile pour les scanners de type Lex   est / \ G ... / gc . Vous pouvez combiner   plusieurs expressions régulières comme celle-ci pour traiter une   chaîne partie par partie, faisant différentes   actions en fonction de quelle expression rationnelle   apparié. Chaque expression rationnelle tente de correspondre   où le précédent s'arrête.

 LOOP:
    {
      print(" digits"),       redo LOOP if /\G\d+\b[,.;]?\s*/gc;
      print(" lowercase"),    redo LOOP if /\G[a-z]+\b[,.;]?\s*/gc;
      print(" UPPERCASE"),    redo LOOP if /\G[A-Z]+\b[,.;]?\s*/gc;
      print(" Capitalized"),  redo LOOP if /\G[A-Z][a-z]+\b[,.;]?\s*/gc;
      print(" MiXeD"),        redo LOOP if /\G[A-Za-z]+\b[,.;]?\s*/gc;
      print(" alphanumeric"), redo LOOP if /\G[A-Za-z0-9]+\b[,.;]?\s*/gc;
      print(" line-noise"),   redo LOOP if /\G[^A-Za-z0-9]+/gc;
      print ". That's all!\n";
    }

Vérifiez également le pQuery comme une façon très agréable de faire ce genre de choses en Perl. des trucs ....

use pQuery;

pQuery( 'http://www.perl.com' )->find( 'a' )->each( 
    sub {
        my $pQ = pQuery( 

Vérifiez également le pQuery comme une façon très agréable de faire ce genre de choses en Perl. des trucs ....

use strict;
use warnings;
use Parse::RecDescent;

my $grammar = q{
    alpha : /\w+/
    sep   : /,|\s/
    end   : '!'
    greet : alpha sep alpha end { shift @item; return \@item }
};

my $parse = Parse::RecDescent->new( $grammar );
my $hello = "Hello, World!";
print "$hello -> @{ $parse->greet( $hello ) }";

# => Hello, World! -> Hello , World !

Toutefois, si vos besoins dépassent le langage HTML / Web, voici ce qui précède: "Hello World!". Exemple dans Parse :: RecDescent ...

<*>

Probablement un trop gros marteau pour casser cet écrou ;-)

); say $pQ->text, ' -> ', $pQ->toHtml; } ); # prints all HTML anchors on www.perl.com # => link text -> anchor HTML

Toutefois, si vos besoins dépassent le langage HTML / Web, voici ce qui précède: "Hello World!". Exemple dans Parse :: RecDescent ...

<*>

Probablement un trop gros marteau pour casser cet écrou ;-)

Modification de l'exemple de Bruno pour inclure la vérification d'erreur:

my $input = "...";
while (1) {
    if ($input =~ /\G(\w+)/gc) { print "word: '$1'\n"; next }
    if ($input =~ /\G(\s+)/gc) { print "whitespace: '$1'\n"; next }

    if ($input !~ /\G\z/gc)  { print "tokenizing error at character " . pos($input) . "\n" }
    print "done!\n"; last;
}

(Notez que l'utilisation de scalar // g est malheureusement le seul endroit où vous ne pouvez vraiment pas éviter d'utiliser les variables $ 1, etc.).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top