🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.perl
11 messages
11 total messages Started by ..:: sjf ::.. Wed, 06 Jan 2010 19:21
Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51736
Author: ..:: sjf ::..
Date: Wed, 06 Jan 2010 19:21
60 lines
2534 bytes
Witam,

Potrzebuję w skrypcie funkcjonalności filtrowania danych z 
wykorzystaniem RE podanego jako opcja do programu, ale z możliwością 
podania zanegowanego RE. Założyłem, że RE poprzedzony przez ! będzie 
traktowany jako zanegowany oraz odpowiednie zastosowanie operatorów =~ i !~.
Niestety sprawdzenie wyniku eval - w wierszu oznaczonym *) na poniższym 
listingu - nie wiele daje, gdyż za każdym razem warunek jest spełniony.

v+
my $re_oper;
if ($opt{g}) {
     if ($opt{g} =~ /^!(.+)$/) {
         $re_oper = "!~";
         $opt{g} = $1;
     }
     else {
         $re_oper = "=~";
     }
     eval { $opt{g} = qr/$opt{g}/ };
     die "** Error in RE \"$opt{g}\":\n$@\n" if $@;
}
foreach (<DATA>) {
     my($host) = /\s*\S+\s+(\S+)/;
     if ($opt{g}) {
         my $expr = "$host $re_oper $opt{g}";
         if ( 1 == eval $expr ) { # *)
             warn "** match \"$opt{g}\" [ $re_oper ] in \"$host\"\n";
             print "$host\n";
         }
     }
     else {
         print "$host\n";
     }
}
v-

Program wykorzystujący analogiczną funkcjonalność eval-a , ale z 
operatorami arytmetycznymi działa poprawnie:
v+
@op = ('+', '-', '*', '/');
for $a(@op) {
     for $b(@op) {
         for $c(@op) {
             for $d(@op) {
                 $_ = "1${a}2${b}3${c}4${d}5";
                 print "$_\n" if 20 == eval $_;
             }
         }
     }
}
v-

W jaki sposób przerobić mój program, aby możliwe było wykorzystanie 
dopasowania RE i zanegowanego RE?

-- 
Szczepan J. Fijał :: sjf @ 50°07'N 18°58'E
xmpp:sjf@jabster.pl | tlen:sjf | gg:2604451 | skype:s.fijal?call
"Linux is like Wigwam. No gates, no windows... Apache inside ;-)"
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51737
Author: Szymon Sokół
Date: Wed, 06 Jan 2010 19:42
15 lines
1724 bytes
On Wed, 06 Jan 2010 20:21:04 +0100, ..:: sjf ::.. wrote:

> foreach (<DATA>) {
>      my($host) = /\s*\S+\s+(\S+)/;
Jaką wartość ma w tym miejscu $host...

>      if ($opt{g}) {
>          my $expr = "$host $re_oper $opt{g}";
...i jaką w rezultacie ma tu $expr?

-- 
Szymon Sokół (SS316-RIPE) -- Network Manager                                 B
Computer Center, AGH - University of Science and Technology, Cracow, Poland  O
http://home.agh.edu.pl/szymon/ PGP key id: RSA: 0x2ABE016B, DSS: 0xF9289982  F
Free speech includes the right not to listen, if not interested -- Heinlein  H
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51744
Author: Tomasz "rocku" K.
Date: Wed, 06 Jan 2010 19:45
24 lines
1496 bytes
..:: sjf ::.. pisze:
> ...
> W jaki sposób przerobić mój program, aby możliwe było wykorzystanie 
> dopasowania RE i zanegowanego RE?

Po co w ogóle stosować eval przy wierszu z gwiazdka? Możesz określić na 
początku czy stosować wersje zanegowaną czy nie, a później:
if ($neg) {
     $host !~ $opt{g}
} else {
     $host =~ $opt{g}
}

Odnośnie samej operacji z evalowaniem wyrażenia, w tym przypadku zdaje 
się działać poprawnie:

$ perl -e '$r=q|"foo" !~ /v/|;  print (1 == eval $r ? "true\n" : "false\n")'
true
$ perl -e '$r=q|"foo" =~ /v/|;  print (1 == eval $r ? "true\n" : "false\n")'
false

-- 
Pozdrawiam,
Tomasz "rocku" K.
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51738
Author: ..:: sjf ::..
Date: Wed, 06 Jan 2010 20:24
18 lines
1546 bytes
W dniu 2010-01-06 20:42, Szymon Sokół pisze:
> On Wed, 06 Jan 2010 20:21:04 +0100, ..:: sjf ::.. wrote:
>
>> foreach (<DATA>) {
>>       my($host) = /\s*\S+\s+(\S+)/;
> Jaką wartość ma w tym miejscu $host...
>
taką jak $1?

>>       if ($opt{g}) {
>>           my $expr = "$host $re_oper $opt{g}";
> ...i jaką w rezultacie ma tu $expr?
myślę, że w związku z powyższym tego już nie muszę wyjaśniać...

-- 
Szczepan J. Fijał :: sjf @ 50°07'N 18°58'E
xmpp:sjf@jabster.pl | tlen:sjf | gg:2604451 | skype:s.fijal?call
"Linux is like Wigwam. No gates, no windows... Apache inside ;-)"
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51745
Author: ..:: sjf ::..
Date: Wed, 06 Jan 2010 20:34
31 lines
2024 bytes
W dniu 2010-01-06 20:45, Tomasz "rocku" K. pisze:
> ..:: sjf ::.. pisze:
>> ...
>> W jaki sposób przerobić mój program, aby możliwe było wykorzystanie
>> dopasowania RE i zanegowanego RE?
>
> Po co w ogóle stosować eval przy wierszu z gwiazdka? Możesz określić na
> początku czy stosować wersje zanegowaną czy nie, a później:
> if ($neg) {
> $host !~ $opt{g}
> } else {
> $host =~ $opt{g}
> }
>
Wiem, od tego zacząłem. Ale zaciekawił mnie sposób z przypisaniem 
operatorów do zmiennej, który w tym przypadku nie bardzo działa.

> Odnośnie samej operacji z evalowaniem wyrażenia, w tym przypadku zdaje
> się działać poprawnie:
>
> $ perl -e '$r=q|"foo" !~ /v/|; print (1 == eval $r ? "true\n" : "false\n")'
> true
> $ perl -e '$r=q|"foo" =~ /v/|; print (1 == eval $r ? "true\n" : "false\n")'
> false
>
Tak, w ten sposób działa - podobnie testowałem.

-- 
Szczepan J. Fijał :: sjf @ 50°07'N 18°58'E
xmpp:sjf@jabster.pl | tlen:sjf | gg:2604451 | skype:s.fijal?call
"Linux is like Wigwam. No gates, no windows... Apache inside ;-)"
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51746
Author: Szymon Sokół
Date: Wed, 06 Jan 2010 21:07
23 lines
2168 bytes
On Wed, 06 Jan 2010 21:34:05 +0100, ..:: sjf ::.. wrote:

> W dniu 2010-01-06 20:45, Tomasz "rocku" K. pisze:
[----]
>> Odnośnie samej operacji z evalowaniem wyrażenia, w tym przypadku zdaje
>> się działać poprawnie:
>>
>> $ perl -e '$r=q|"foo" !~ /v/|; print (1 == eval $r ? "true\n" : "false\n")'
>> true
>> $ perl -e '$r=q|"foo" =~ /v/|; print (1 == eval $r ? "true\n" : "false\n")'
>> false
>>
> Tak, w ten sposób działa - podobnie testowałem.

...z czego łatwo wywnioskować, że sama konstrukcja jest w porządku, a
problem leży w Twoich konkretnych danych. A na moje pytanie o te dane
udzieliłeś odpowiedzi, którą przy maksimum dobrej woli mogę nazwać
wymijającą. 
-- 
Szymon Sokół (SS316-RIPE) -- Network Manager                                 B
Computer Center, AGH - University of Science and Technology, Cracow, Poland  O
http://home.agh.edu.pl/szymon/ PGP key id: RSA: 0x2ABE016B, DSS: 0xF9289982  F
Free speech includes the right not to listen, if not interested -- Heinlein  H
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51742
Author: ..:: sjf ::..
Date: Thu, 07 Jan 2010 21:27
61 lines
2927 bytes
W dniu 2010-01-06 20:42, Szymon Sokół pisze:
> On Wed, 06 Jan 2010 20:21:04 +0100, ..:: sjf ::.. wrote:
>
>> foreach (<DATA>) {
>>       my($host) = /\s*\S+\s+(\S+)/;
> Jaką wartość ma w tym miejscu $host...
>
>>       if ($opt{g}) {
>>           my $expr = "$host $re_oper $opt{g}";
> ...i jaką w rezultacie ma tu $expr?
>
Ok, podrzucę trochę przykładowych danych - powinno to rzucić więcej 
światła na problem:

sekcja __DATA__ w skrypcie:
v+
10.19.171.25    ww_w121
10.19.171.17    ww_w122
10.19.171.24    ww_w123
10.19.171.150   kt_e111
10.19.171.148   kt_e112
10.19.171.149   kt_e113
10.19.171.5     pz_w101
10.19.171.6     pz_w103
10.19.171.7     gd_e111
10.19.171.75	gd_e121
10.19.171.76	wr_e121
10.19.171.77	wr_w103
10.19.171.6     gd_w101
10.19.171.4     pz_e121
10.19.171.5     wr_w101
10.19.171.10	gd_w102
10.19.171.4	wr_e111
10.19.171.5	wr_w102
v-

Przykład 1) Skrypt uruchomiono z opcją -g = "kt_", tak więc w wyniku 
powinienem otrzymać:
kt_e111
kt_e112
kt_e113

Przykład 2) Skrypt uruchomiony z opcją -g = "!ww_" powinien w rezultacie 
wypisać wszystkie powyższe nazwy (z sekcji DATA) poza ww_w121, ww_w122, 
ww_w123.

W przypadku zastosowania sposobu z testowaniem czy RE "normalny" czy 
zanegowany i odpowiednim ustawieniem zmiennej - podobnie jak 
zaproponował Tomasz "rocku" K. - działa w porządku.  Niestety w 
rzeczywistości opcja g składa się z kilku RE oddzielonych za pomocą 
przecinka - taką założyłem składnię - z których każdy ma zostać 
dopasowany do nazw z listy jako logiczny AND.

Czyli przykład 3) Uruchomienie z opcją g = "!ww_,!kt_", w zamierzeniu 
chcę otrzymać listę wszystkich hostów z __DATA__ poza ww_w121, ww_w122, 
ww_w123, kt_e111, kt_e112, kt_e113.

-- 
Szczepan J. Fijał :: sjf @ 50°07'N 18°58'E
xmpp:sjf@jabster.pl | tlen:sjf | gg:2604451 | skype:s.fijal?call
"Linux is like Wigwam. No gates, no windows... Apache inside ;-)"
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51743
Author: Szymon Sokół
Date: Thu, 07 Jan 2010 22:34
42 lines
2901 bytes
On Thu, 07 Jan 2010 22:27:23 +0100, ..:: sjf ::.. wrote:

> W przypadku zastosowania sposobu z testowaniem czy RE "normalny" czy 
> zanegowany i odpowiednim ustawieniem zmiennej - podobnie jak 
> zaproponował Tomasz "rocku" K. - działa w porządku.  Niestety w 
> rzeczywistości opcja g składa się z kilku RE oddzielonych za pomocą 
> przecinka - taką założyłem składnię - z których każdy ma zostać 
> dopasowany do nazw z listy jako logiczny AND.
> 
> Czyli przykład 3) Uruchomienie z opcją g = "!ww_,!kt_", w zamierzeniu 
> chcę otrzymać listę wszystkich hostów z __DATA__ poza ww_w121, ww_w122, 
> ww_w123, kt_e111, kt_e112, kt_e113.

No to to już nie jest takie do końca trywialne, najprościej pewnie będzie
podzielić te regexpy na dwie grupy - zanegowane i niezanegowane - a potem
obrabiać osobno. Ja bym to zrobił jakoś tak:

my(@positive, @negative);
for my $re (split /,/, $opt{g}) {
  if($re =~ s/^!//) { 
    push @negative, $re;
  } else {
    push @positive, $re;
} 
my $p_re = join '|', @positive;
eval { $p_re = qr/$p_re/; }
die "** Error in RE \"$p_re\":\n$@\n" if $@;
my $n_re = join '|', @negative;
eval { $n_re = qr/$n_re/; }
die "** Error in RE \"$n_re\":\n$@\n" if $@;
foreach (<DATA>) {
  my($host) = /\s*\S+\s+(\S+)/;
  print "$host\n"
    unless @negative and $host =~ $n_re 
        or @positive and $host !~ $p_re; # z prawa de Morgana 
}

-- 
Szymon Sokół (SS316-RIPE) -- Network Manager                                 B
Computer Center, AGH - University of Science and Technology, Cracow, Poland  O
http://home.agh.edu.pl/szymon/ PGP key id: RSA: 0x2ABE016B, DSS: 0xF9289982  F
Free speech includes the right not to listen, if not interested -- Heinlein  H
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51739
Author: Maciej Misiak
Date: Wed, 13 Jan 2010 14:17
15 lines
1431 bytes
..:: sjf ::.. pisze:
> W dniu 2010-01-06 20:42, Szymon Sokół pisze:
>> On Wed, 06 Jan 2010 20:21:04 +0100, ..:: sjf ::.. wrote:
>>
>>>       if ($opt{g}) {
>>>           my $expr = "$host $re_oper $opt{g}";
>> ...i jaką w rezultacie ma tu $expr?
> myślę, że w związku z powyższym tego już nie muszę wyjaśniać...

A jak by tak zmienić na
my $expr = "$host $re_oper /$opt{g}/";
?

-- 
grizzley
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51740
Author: ..:: sjf ::..
Date: Wed, 13 Jan 2010 20:39
19 lines
1717 bytes
W dniu 2010-01-13 15:17, Maciej Misiak pisze:
> ..:: sjf ::.. pisze:
>> W dniu 2010-01-06 20:42, Szymon Sokół pisze:
>>> On Wed, 06 Jan 2010 20:21:04 +0100, ..:: sjf ::.. wrote:
>>>
>>>> if ($opt{g}) {
>>>> my $expr = "$host $re_oper $opt{g}";
>>> ...i jaką w rezultacie ma tu $expr?
>> myślę, że w związku z powyższym tego już nie muszę wyjaśniać...
>
> A jak by tak zmienić na
> my $expr = "$host $re_oper /$opt{g}/";
> ?
Nic z tego - tak też próbowałem.

-- 
Szczepan J. Fijał :: sjf @ 50°07'N 18°58'E
xmpp:sjf@jabster.pl | tlen:sjf | gg:2604451 | skype:s.fijal?call
"Linux is like Wigwam. No gates, no windows... Apache inside ;-)"
Re: Walidacja wyrażenia regularnego - operatory =~ i !~ jako zmienna
#51741
Author: Maciej Misiak
Date: Sat, 16 Jan 2010 23:27
27 lines
1891 bytes
..:: sjf ::.. pisze:
> W dniu 2010-01-13 15:17, Maciej Misiak pisze:
>> ..:: sjf ::.. pisze:
>>> W dniu 2010-01-06 20:42, Szymon Sokół pisze:
>>>> On Wed, 06 Jan 2010 20:21:04 +0100, ..:: sjf ::.. wrote:
>>>>
>>>>> if ($opt{g}) {
>>>>> my $expr = "$host $re_oper $opt{g}";
>>>> ...i jaką w rezultacie ma tu $expr?
>>> myślę, że w związku z powyższym tego już nie muszę wyjaśniać...
>>
>> A jak by tak zmienić na
>> my $expr = "$host $re_oper /$opt{g}/";
>> ?
> Nic z tego - tak też próbowałem.

Hmm, mi działa. Wypisuje dokładnie to, co opisałeś, czyli
kt_e111
kt_e112
kt_e113
w pierwszym przypadku i wszystkie niepasujące do  !~/ww_/ w drugim.

-- 
grizzley

PS. sorry za tak długie nieodpisywanie, jeszcze po Nowym Roku problemy z 
nadążeniem za otaczającym światem...
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads