String matchen

Hallo!

Mal ne Frage. Wenn ich einen Text/String habe also z.B. $string = „bla bla bla“ und ich diesen mit RegExpr auf Wörter mit einer bestimmten Länge überprüfen möchte. Z.B. sollen Wörter gematcht werden, die eine Buchstabenanzahl zwischen 5 - 8 Zeichen haben. Wie stelle ich das aber an, wenn es mehre Wörter in diesem String gibt auf die dieses Kriterium zutrifft?

if ($a =~ /\b(\w{5,8})\b/i)
{ print $1;
$hash{$1} = 1;
}
else
{ print „Nichts gefunden“; }

Diese Stück Code hört immer auf, sobald er ein passendes Kriterium gefunden hat, egal ob weiter hinten im Text noch ein anderes passendes Wort existiert.
Wie stelle ich es also an, dass er alle Wörter untersucht? Muss ich den String splitten und dann einzeln mit den RegExpr prüfen oder geht das auch anders???

Danke
Reen

Hallo René,

Mal ne Frage. Wenn ich einen Text/String habe also z.B.
$string = „bla bla bla“ und ich diesen mit RegExpr auf Wörter
mit einer bestimmten Länge überprüfen möchte. Z.B. sollen
Wörter gematcht werden, die eine Buchstabenanzahl zwischen 5 -
8 Zeichen haben. Wie stelle ich das aber an, wenn es mehre
Wörter in diesem String gibt auf die dieses Kriterium zutrifft?

mit /g

if ($a =~ /\b(\w{5,8})\b/i)
{ print $1;
$hash{$1} = 1;
}
else
{ print „Nichts gefunden“; }

my $text = „bla bla blalfl jdjdjdj dh“;
my %hash = ();

++$hash{ $_ } for $text =~ /\b\w{5,8}\b/g;
…D.h., das ‚for‘ erzeugt einen Listenkontext
auf die Regex, diese liefert dann bei /g eine
Liste aller Hits, welche nacheinander als $_
aus der ‚for‘ Schleife abgerufen werden
können.

Grüße

CMБ

Hallo!

danke das funzt wunderbar. Aber leider kann ich ist dieses Stück Code irgendwie schwer nachvollziehbar für mich als Perl-Anfänger. Gibts dazu auch ne klassische Methode für den Code? Also so richtig schön mit einer FOR-Schleife und dann das Ganze klassisch in einen Hash schreiben?

Danke

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo,


my $text = „bla bla blalfl jdjdjdj dh“;
my %hash = ();

++$hash{ $_ } for $text =~ /\b\w{5,8}\b/g;

D.h., das ‚for‘ erzeugt einen Listenkontext

danke das funzt wunderbar. Aber leider kann ich ist dieses
Stück Code irgendwie schwer nachvollziehbar für mich als
Perl-Anfänger. Gibts dazu auch ne klassische Methode für den
Code? Also so richtig schön mit einer FOR-Schleife und dann
das Ganze klassisch in einen Hash schreiben?

Du kannst es z.B. so machen:

my $text = "bla bla blalfl jdjdjdj dh";
my @matches = $text =~ /\b\w{5,8}\b/g;
# jetzt enthält @matches alle gefunden Wörter.
foreach my $word (@matches){
 # jetzt enthält $word der Reihe nach alle Wörter
 # hier machen, was immer du damit anstellen willst.
}

oder kürzer:

foreach ($text =~ /\b\w{5,8}\b/g){
 # jetzt enthält $\_ nacheinander alle Wörter
}

Und da for das gleiche ist wie foreach, kann man das auch zu dem verkürzen, was vorher geschrieben wurde.

Grüße,
Moritz

Super…danke euch beiden!

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo René

Super…danke euch beiden!

Weil das so ein schönes Beispiel ist, kann
man daraus prima eine Vorstellung verschiedner
Perl-Techniken machen (ich mach das jetzt mal).

Nehmen wir an, Du hast einen Text (wie gegeben) und
möchtest alle Worte zwischen 5 u. 8 Zeichen ermitteln
und deren Anzahl in einem Hash ablegen.

Da gibt es einige unterschiedliche Formulierungen.
Ich nenne sie mal, teilweise mit Kommentaren:

use warnings;
use strict;


my $text = "bla bla blalfl jdjdjdj dh";

{
 my %hash; # idiomatische while /g - Schleife (+ capture $1)
 # Regexp in Skalarkontext + /g setzen
 while( $text =~ /\b(\w{5,8})\b/g ) {
 $hash{ $1 }++
 }
}


{
 my %hash; # Listenkontext mit 'goatse'-Operator ()
 # + code assertion (+ capture $1)
 () = $text =~ /\b(\w{5,8})\b(?{ $hash{ $1 }++ })/g;
}


{
 my %hash; # alle Hits in ein Array ziehen, dann Array auswerten 
 my @matches = $text =~ /\b\w{5,8}\b/g; # Regexp in Listenkontext ==\> Hits
 # (Moritz) 
 foreach my $word (@matches){
 $hash{$word}++;
 }
}


{
 my %hash; # alle Hits 'direkt' aus einem Listenkontext
 # ziehen (wie oben)
 ++$hash{ $\_ } for $text =~ /\b\w{5,8}\b/g;
}


{
 my %hash; # Listenkontext durch 'map' erzeugen
 # (analog zu Darueberstehendem)
 map ++$hash{ $\_ }, $text =~ /\b\w{5,8}\b/g;
}

Einige Varianten sind eher für Fort-
geschrittene, die anderen sog. Standard-Idiome.

Manche benötigen explizites Capturing nach $1,
manche (im Listenkontext) nicht.

Grüße

CMБ