Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]8880[/thread]

pos($string) zwischen //g Regexes in Schleife?



<< >> 10 Einträge, 1 Seite
GoodFella
 2007-03-27 18:55
#75444 #75444
User since
2007-01-09
192 Artikel
BenutzerIn
[default_avatar]
Hi,
ich schreibe gerade an einem Script, dass in einer Schleife nach Mustern eines sich mit dem Inhalt einer foreach-Schleifenvariable verändernden Strings sucht; diese Suche soll bestimmte Werte zurückliefern, weswegen ich den global-Modifier verwende.
Angenommen, ich suche per Regex das erste Mal und er findet etwas. Perl setzt pos dann automatisch an dieses Offset. Dann kommt der nächste Schleifendurchlauf. Jetzt soll er wieder bei 0 anfangen zu suchen, also muss ich pos immer auf 0 zurücksetzen.
Ist relativ unelegant finde ich; also: gibt es dafür eine elegantere Lösung?

perldoc habe ich schon befragt:

Quote
C:\Dokumente und Einstellungen\Administrator>perldoc -f pos
pos SCALAR
pos Returns the offset of where the last "m//g" search left off for
the variable in question ($_ is used when the variable is not
specified). Note that 0 is a valid match offset. "undef"
indicates that the search position is reset (usually due to
match failure, but can also be because no match has yet been
performed on the scalar). "pos" directly accesses the location
used by the regexp engine to store the offset, so assigning to
"pos" will change that offset, and so will also influence the
"\G" zero-width assertion in regular expressions. Because a
failed "m//gc" match doesn't reset the offset, the return from
"pos" won't change either in this case. See perlre and perlop.
PerlProfi
 2007-03-27 19:29
#75445 #75445
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Falls du nur den g modifier verwendest solltest du keine Probleme bekommen, oder hast du mal ein kleines Beispiel, wo es schief geht?

MfG
GoodFella
 2007-03-28 00:57
#75446 #75446
User since
2007-01-09
192 Artikel
BenutzerIn
[default_avatar]
[quote=PerlProfi,27.03.2007, 17:29]Falls du nur den g modifier verwendest solltest du keine Probleme bekommen, oder hast du mal ein kleines Beispiel, wo es schief geht?

MfG[/quote]
jo, klar doch.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl

use strict;
use warnings;

my $str = 'bla_blub_bla';

$str =~ /([^_]+)_/sg;
print '1. Mal: Position='.pos($str).", Gefunden: $1\n";
$str =~ /([^_]+)_/sg;
print '2. Mal: Position='.pos($str).", Gefunden: $1\n";


Output:

Quote
1. Mal: Position=4, Gefunden: bla
2. Mal: Position=9, Gefunden: blub


Ich möchte, dass er IMMER bei Offset bzw. Position 0 mit der Suche anfängt, allerdings ist es lästig, immer nach dem Regex

Code (perl): (dl )
pos($str) = 0;


zu schreiben; ich verwende sehr viele Regexe in dem besagten Script, die sich genauso verhalten sollen. Gibt es dafür eine elegante Umgehung? Am besten wär natürlich ein Modifier, aber den gibts nicht afaik :)
betterworld
 2007-03-28 05:26
#75447 #75447
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
Eine Moeglichkeit waere, den String zu modifizieren:
Code (perl): (dl )
$str .= '';

Die Entscheidung, ob das eleganter ist, ueberlasse ich Dir.
GoodFella
 2007-03-28 11:24
#75448 #75448
User since
2007-01-09
192 Artikel
BenutzerIn
[default_avatar]
Naja, ist auch jedesmal eine Zeile nach dem Regex .. und nicht dafür gedacht... so wie pos.
Hmm... wenn man jetzt irgendwie in die Schleifenanweisung einbaut, dass die Var jedesmal anders aber irgendwie gleich ist... hmmmmmmmmmmm........ nur wie...
Taulmarill
 2007-03-28 12:31
#75449 #75449
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
was hältst du davon:
Code: (dl )
1
2
3
4
5
my $str = 'bla_blub_bla';
$str =~ /([^_]+)_/s;
print '1. Mal: Position='.$+[0].", Gefunden: $1\n";
$str =~ /([^_]+)_/s;
print '2. Mal: Position='.$+[0].", Gefunden: $1\n";


perlvar\n\n

<!--EDIT|Taulmarill|1175070769-->
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
GoodFella
 2007-03-28 15:36
#75450 #75450
User since
2007-01-09
192 Artikel
BenutzerIn
[default_avatar]
[quote=Taulmarill,28.03.2007, 10:31]was hältst du davon:
Code: (dl )
1
2
3
4
5
my $str = 'bla_blub_bla';
$str =~ /([^_]+)_/s;
print '1. Mal: Position='.$+[0].", Gefunden: $1\n";
$str =~ /([^_]+)_/s;
print '2. Mal: Position='.$+[0].", Gefunden: $1\n";


perlvar[/quote]
cool... dachte, ich hätte mal gelesen, dass speichern in $1, $2, ... nur in Verbindung mit dem g-Modifier funktioniert...
Schön, dass es anders ist :D
Danke.

Achja, der betroffene Part von perlvar sagt:
Quote
$LAST_PAREN_MATCH
$+ The text matched by the last bracket of the last successful
search pattern. This is useful if you don't know which one of a
set of alternative patterns matched. For example:

/Version: (.*)|Revision: (.*)/ && ($rev = $+);

(Mnemonic: be positive and forward looking.) This variable is
read-only and dynamically scoped to the current BLOCK.
}

Dass die Position bei Listenkontext in $+[0] steht, davon finde ich aber nichts.. In $+[1] befindet sich nach meinen Tests ($+[0] - 1) .. keine Ahnung welchen Zweck das hat.. oder hab ich was überlesen? :)
betterworld
 2007-03-28 16:08
#75451 #75451
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
Und ich dachte, Du haettest irgend einen Grund dafuer, /g zu benutzen :) Hatte schon gedacht "guter Witz", als ich den Beitrag von Taulmarill gelesen habe ;)
PerlProfi
 2007-03-28 16:41
#75452 #75452
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
[quote=GoodFella,28.03.2007, 13:36]Dass die Position bei Listenkontext in $+[0] steht, davon finde ich aber nichts.. In $+[1] befindet sich nach meinen Tests ($+[0] - 1) .. keine Ahnung welchen Zweck das hat.. oder hab ich was überlesen? :)[/quote]
Du hast dir nur die falsche Variable angesehen:
Quote
@LAST_MATCH_END
@+

This array holds the offsets of the ends of the last successful submatches in the currently active dynamic scope. $+[0] is the offset into the string of the end of the entire match. This is the same value as what the pos function returns when called on the variable that was matched against. The nth element of this array holds the offset of the nth submatch, so $+[1] is the offset past where $1 ends, $+[2] the offset past where $2 ends, and so on. You can use $#+ to determine how many subgroups were in the last successful match. See the examples given for the @- variable.


Aber ich verstehe nicht, wieso die Position nicht zurück gesetzt wird, folgendes funktioniert nämlich wie erwartet:
Code: (dl )
1
2
3
4
5
6
7
8
#!/usr/bin/perl
use strict;
use warnings 'all';

my $str = 'bla_blub_bla';

print( $str =~ /([^_]+)_/g , "\n");
print( $str =~ /([^_]+)_/g , "\n");


MfG
Taulmarill
 2007-03-28 17:16
#75453 #75453
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
Das liegt daran, dass du den Regex nicht im scalaren, sondern im Listenkontext hast. Durch den Listenkontext gibt der Regex alle Werte und nicht nur den ersten zurück, wodurch dann der nächste Regex auch wieder von Vorne beginnt.
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
<< >> 10 Einträge, 1 Seite



View all threads created 2007-03-27 18:55.