Linux - Reguläre Ausdrücke - Gruppe zurückgeben



  • Hallo,

    ich hole mir öfters ein paar Infos aus HTML-Seiten aus dem Internet. Die gewünschten Daten filtere ich mir immer mit grep raus. Unter Perl gibt es eine Möglichkeit mit der man eine Gruppe aus dem String selektieren kann.

    z.B.:
    <h1>(.*?)</h1>

    Bei <h1>abc</h1> würde ich dann über $1 abc bekommen (wenn ich das jetzt richtig verstanden habe).

    Jetzt gibt es ja pcregrep (grep was perl-kompatible reguläre Ausdrücke verwendet). Ist es mit diesem Programm auch das o.g. möglich (scheint nicht so)? Bzw. kennt jemand ein anderes Programm was das kann? Alternativ müsste ich mir halt mit Perl so ein Skript basteln, habe aber leider noch keine Ahnung von Perl.

    Ich verwende Debian testing.

    Danke! 🙂



  • weis jetzt gar nicht ob das geht mit grep
    aber grep ist schnell nachgebaut 🙂

    #!/bin/perl
    use strict;
    use warnings;
    
    #hole pattern und filename aus der argumenten liste
    my $pattern = shift @ARGV;
    my $file = shift @ARGV;
    
    open INFILE, $file
        or die, "Cannot open $file: $!";
    while (<INFILE>) {
        if(/$pattern/) {
            print "$1\n";
        }
    }
    close INFILE;
    

    aufruf dann so:

    me@mypc:~$perl namedesscripts.pl "<h1>(.*)<\/h1>" index.html
    


  • ahja vielleicht hilft dir der weiter:
    http://www.linux.com/feature/52837

    und wenns wirklich nur der titel sein soll:

    grep '<h1>' index.html | cut -d '>' -f 2 | cut -d '<' -f 1
    


  • Hallo,

    danke das sieht schon mal gut aus.

    Habe es ein wenig abgeändert:

    #!/usr/bin/perl
    
    my $pattern = shift @ARGV;
    my $n = shift @ARGV;
    
    if($n == "") {
        $n = _;
    }
    
    while (<STDIN>) {
        if(/$pattern/) {
            print "$$n\n";
        }
    }
    

    Problem ist nur noch dass er nur einmal pro Zeile matcht.

    Mit

    echo '<h1>123</h1>  <h1>234</h1>' |./bla.pl '<h1>(.*?)</h1>' 1
    

    bekomme ich nur 123 zurück. Noch eine Idee dazu? Zeilenübergreifend wäre auch noch schön. Aber wie es aussieht geht das nicht so einfach mit perl. Ich probiere noch weiter. 🙂

    Oliver



  • Oliver schrieb:

    Problem ist nur noch dass er nur einmal pro Zeile matcht.

    Mit

    echo '<h1>123</h1>  <h1>234</h1>' |./bla.pl '<h1>(.*?)</h1>' 1
    

    bekomme ich nur 123 zurück. Noch eine Idee dazu? Zeilenübergreifend wäre auch noch schön. Aber wie es aussieht geht das nicht so einfach mit perl. Ich probiere noch weiter. 🙂

    Oliver

    mit perl geht fast alles, sieht dann halt entsprechend aus 😃
    also was willst du genau machen? alle inhalte eines spezifischen tags rausholen richtig? (ein html file sollte eh nicht mehr als ein <h1> tag haben, aber das is nebensache:))
    lass mich mal n bisschen wursteln..



  • bidde schööön 😃

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    my $tag = shift @ARGV;
    my $file = shift @ARGV;
    $/ = "";
    
    open INFILE, $file
        or die "Cannot open $file: $!";
    while (<INFILE>) {
        while($_ =~ /$tag((\w*|\s*)+)<\//cg) {
            print "$1\n";
        }
    }
    close INFILE;
    

    getestet mit folgendem file:

    <h1>123</h1> <h1>234</h1>
    <h1>234 </h1>
    <h1>23 4</h1>
    <h1>23545
    3246476</h1>



  • Hallo,

    vielen Dank für das Skript und die viele Mühe! Aber irgendwie wollte das nicht so recht wie ich wollte. Hab mir jetzt (bzw. mit jemand anderem) ein kleines Skript in Python geschrieben:

    #!/usr/bin/env python
    
    import sys
    import re
    
    if len(sys.argv) < 2:
        sys.exit()
    
    for r in re.findall(sys.argv[1], sys.stdin.read()):
        print r
    

    Das macht aus:

    wget -qO - http://www.ibood.com/site/de/ibood.php |grep productTitle |egrep -o '>.*<' |egrep -o '[^>][^<]*' |head -n1
    

    nun:

    wget -qO - http://www.ibood.com/site/de/ibood.php |pygrep '.*productTitle.*>(.*)<'
    

    Das erste geht bestimmt auch noch kürzer - ist alles nur quick & dirty.

    Oliver


Anmelden zum Antworten