Newsgroup: it.comp.lang.perl
Titolo: problema di matching

la storia infinita... :-)
 
Sempre alle prese col Bot IRC, risolti quasi tutti i problemi, mi sono 
accorto del problema dell'ultima ora.
 
Vedo di spiegarmi:
 
Quando un utente entra nella chat, una regex estrapola il nick e lo 
confronta con quelli memorizzati nel DB, la riga di codice con la regex è 
questa:
 
 if ($answer  =~ /:(.*)!.+?(JOIN)\s:($chan)/) {
 
in $1 ho il nick di chi entra,
 
una regex simile è presente su altre righe dove ci sono i comandi per 
aggiungere o cancellare elementi sul DB, una è questa:
 
if ($answer =~ /:(.*)!.+?(PRIVMSG)(.+?)\s:\!add\s(.*)/) {
 
in $1 ho il nick di chi chiama il comando, in $4 ho il nick da 
aggiungere/togliere al/dal DB.
 
Ora fino a che chi entra si chiama gino, paolo, limortaccisua,  o una 
qualunque parola che usa normali caratteri ASCII, funziona tutto 
perfettamente, se però nel nick vengono usati caratteri "alieni" tipo 
^pippo^, funziona solo la scrittura del nick nel DB, mentre non funziona la 
cancellazione, e con il nick ^pippo^ regolarmente memorizzato se appunto 
prova ad entrare ^pippo^, non viene riconosciuto.
 
evidentemente il .* non matcha il ^, ma se così fosse, non mi spiego che il 
comando !add ^pippo^ scriva regolarmente... Ho provato a pasticciare un poco 
con la regex, ma i risultati sono stati scarsi...
 
/:(.*)!.+?(PRIVMSG)(.+?)\s:\!add\s(\W*.*\W*)/
/:(.*)!.+?(PRIVMSG)(.+?)\s:\!add\s(\^*.*\^*)/
 
non funzionano.
 
-- 
Fri(END), Boyfri(END), Girlfri(END), Bestfri(END). Everything has an END 
except...Fam(ILY)! It Has 3 Letters that say I LOVE YOU 
 

 appunto prova ad entrare ^pippo^, non viene riconosciuto.
 
non è un problema di regex, ho trovato un programma (The regex Coach) che mi 
dice che "tutto va bene", il problema è che adesso non ho idea su cosa 
indagare...



 
In questi casi si va di debugger
Per fortuna il debugger perl è facile da usare
 

 Per fortuna il debugger perl è facile da usare
 
eh... 'nsomma :) sono punti di vista..
A sapere cosa guardare, perchè ho provato a fare il trace e non ho nessun 
errore visibile, anche perchè in fin dei conti l'errore non c'è, non almeno 
a livello logico.
 
Quindi io ho un array (su disco), con questo script:
 
#!/usr/local/bin/perl
 use strict;
 use Tie::File;
 my @database;
 tie @database, 'Tie::File', 'database.dat';
foreach my $test(@database) {
       print "$test\n";
                     }
untie @database;
 
ottengo questo output:
 
liftman@prove:~$ perl -w 
prova.pl
 
gino
liftman
^pino^
^pino^
^pino^
toto
carlo
 
le istruzioni che ho sullo script per controllare la presenza di un nome 
funzionano perfettamente per i nomi "normali", la presenza multipla di 
"^pino^ è dovuta al fatto che comunque vada, qualsiasi combinazione che usi 
non viene trovato nel l'array.
 
Il codice che segue controlla che il nick, nel caso dell'esempio sotto che 
entra nel canale, sia o meno presente nell'array.
$utente banalmente è il nick in questione.
 
 if ($answer  =~ /:(.*)!.+?(JOIN)\s:($chan)/) {
      $utente = $1;
      &checkDB($utente);
          if ($trovato2 eq $utente) {
              print $server "PRIVMSG $chan : Benvenuto su $chan  $utente 
\r\n" if $utente ne $nick;
            }
            else {
              print $server "PRIVMSG $chan : $utente non risulta nel 
database \r\n";
              print $server "MODE $chan +b $utente \r\n";
              print $server "KICK $chan $utente Questo e' un chan PRIVATO, 
contatta un operatore!\r\n";
              &unban($utente);
                }
      }
 
sub checkDB {
$trovato2 = first { /$utente/ }  @database;
 if (defined $trovato2) { return $trovato2 }
      else {
      $trovato2 = "assente";
      return $trovato2;
      }
}
 
il difetto oltre che con i ^ c'è anche con altri caratteri tipo le 
parentesi, il punto di domanda e chissà quali altri che per fortuna non sono 
tutti usabili per scriversi un nick, anche se su certe combinazioni lo 
script si incazza (se uso [gino si chiude tutto, ma con [gino] è ok) .. ma 
questo lo posso risolvere dopo con calma, al momento che sono sicuro che ciò 
che scrivo sull'array lo posso rileggere con certezza.



qui fa una ricerca del nome utente prendendolo come pattern per una regex
credo he l' utente debba matchare carattere per carattere nel db quindi:
 
 
if (grep($utente eq $_, @data))  ...
 
 
 
 
 
 
 
 
 
 

 if (grep($utente eq $_, @data))  ...
 
Le mie capacità programmatorie sono limitate, e pure la conoscenza del perl, 
ma sela regex viene soddisfatta alla fine un sistema o un altro non dovrebbe 
fare differenza ai fini del risultato.
 
in definitiva in una regex (.*) soddisferebbe praticamente tutte le 
combinazioni possibili ed immaginabili almeno basandomi su queste poche 
righe di codice:
#!/usr/bin/perl
 use strict;
my $test = <STDIN>;
chomp $test;
 if ($test =~ /.*/) {
     print("$test riconosciuto\n");
  }
  else {
     print("$test non riconosciuto\n");
  }
 
comprendendo pure praticamente tutto quello che ho trovato sulla tastiera. 
Il problema è che apparentemente la funzione first() ha un problema con i 
caratteri che non  siano quelli dell'alfabeto...
 
#!/usr/local/bin/perl
 use strict;
 use List::Util qw(first);
 use Tie::File;
 my @database;
 
 my $chiave = '^pino^';
tie @database, 'Tie::File', 'database.dat';
 
my $prova = first { /$chiave/ } @database;
print "il valore di \$prova e' $prova\r\n";
untie @database;
 
liftman@prove:~$ perl -w 
prova.pl
 
Use of uninitialized value $prova in concatenation (.) or string at 
prova.pl
 
line 11, <$fh> line 10.
il valore di $prova e'
liftman@prove:~$
 
mentre se cambio con "my $chiave = 'liftman';" (che è presente nel DB)
 
liftman@prove:~$ perl -w 
prova.pl
 
il valore di $prova e' liftman
liftman@prove:~$
 
in definitiva se i "^" (così come altri caratteri) sono considerati normali 
caratteri alfanumerici, la funzione first() ha un bug, quindi devo cambiare 
sistema, sperando che non sia l'unica a non digerire caratteri strani. ora 
ho la testa che mi gira a forza di far prove, aggiunte e correzioni, domani 
cerco di riprendere in mano la situazione.



al di la di come funziona una regexp qui esiste un proprio buco logico a 
trattare il nome utente come una regexp
E se il nome utente poi conterebbe simboli che invalidano una regexp che 
fai ?
Il programma va in crash od emetterebbe un warning (dipende dal 
problema) ma comunque non darebbe un risultato valido
 
per cercare un nome utente usa grep con confronto per uguaglianza, 
sicuramente piu affidabile e corretto per la ricerca di un utente
 
 
 

 sicuramente piu affidabile e corretto per la ricerca di un utente
 
Alla fine il mio scopo è di imparare, e proverò ancora molto prima di 
gettare la spugna, mi ci vorrebbe un buon libro in italiano, dato che il mio 
inglese è se vogliamo ancora più scarso della conoscenza del perl :)



Non che devi fare a meno delle regexp
Ne devi fare di quelle non controllate
Se una regexp la scrivi tu è controllata ma se è da una fonte esterna no 
a meno di controllarla prima
Ma,ripeto, in questo caso non serve
Vai di grep
 


dimenticavo:
http://www.perl.it/modern_perl/modern_perl.pdf
 
 
In Italiano
 

 In Italiano
 
Grazie, non è comodo (*) come un libro, ma meglio che niente..
(*) il libro lo leggi a letto, in (soprattutto..) bagno e lo gusti di più 
:-)



 
certamente,ma questo è gratis e scritto bene
Se vuoi un libro cartaceo puoi andare sul camel book edizione italiana 
ma ce ne sono anche altri
 
Fun with Perl
 

 ce ne sono anche altri
 
non recentissimamente, ma il camel book italiano e pure anche altri libri 
sempre in italiano risultavano introvabili, sia on line che in libreria.
Fino ad ora mi sono avvalso oltre a google ovviamente, solo a "Pocket Perl" 
e "Perl & Internet", che per principiare vanno pure bene, ma per ovvii 
motivi trattano solo superficialmente l'argomento.
