PDA

Visualizza la versione completa : Problema \n (New Line) in Epressioni Regolari


zamak
20-12-2004, 17:52
Ciao a tutti,

non capisco come mai nel seguente codice la condizione basata sull'espressione regolare risulta NON Vera;

stampando a video sia $ref che $_ ho verificato la corrispondenza come segue:

$ref = 023456789
$_ = 000000000000|023456789\n (naturalmente invece di \n a video la linea va a capo dopo il 9)

se ometto la \n finale cosi: (/\|$ref/i), l'espressione risulta vera; perchè?




while(<DATA>) {

if(/\|$ref\n/i) {
next;
}

}

Mich_
21-12-2004, 09:27
Per usare la \n dentro la RE, questa non deve fermarsi a fine riga (il default), per cui devi aggiungere /s alla fine.
Esempio:
if(/\|$ref\n/is) {

zamak
21-12-2004, 10:21
Ciao Mich_,

Purtroppo avevo già provato come dici (con s (single line)) tu senza successo:
/\|$ref\n/is

inoltre secondo lo stesso criterio dovrebbe funzionare anche (e non funziona):
/\|$ref$/i

L'unico sistema che funziona è il più generico:
/\|$ref.?$/i
con il quale essendoci sicuramente il carattere \n in fondo alla linea il '.' non potrà che essere \n per forza;
il fatto che questo codice funzioni mi fa supporre che la linea sia considerata singola di default (anche senza la s);
il fatto che questo funzioni non mi soddisfa comunque... perchè tutte queste "stranezze"?

grazie comunque della risposta, aspettando con piacere tuoi e altri interventi.

Ciao e Auguri,

Mich_
21-12-2004, 11:37
Stai usando Perl? Quale versione?

Perche` io sto facendo un'applicazione in Perl (no CGI) in cui uso pesantemente le RE e uso correntemente il \n con il /s.
Se non faccio errori (cosa assai frequente: le RE le devo scrivere almeno tre volte prima che funzionino), funziona perfettamente.

Io uso "This is perl, v5.6.1 built for i386-linux"
(basta dare il comando "perl -vers" per avere quella stringa).

zamak
21-12-2004, 15:02
lo script gira su una macchina con Perl v5.8.3

però sono quasi convinto di aver usato \n nelle RE con successo in passato, ma non ricordo se in quel periodo la macchina girava ancora con il 5.6 (che è stato poi aggiornato); mi sembra comunque strano che possa esserci una differenza del genere tra queste due versioni, ora vado a cercare su perldoc e se trovo qualcosa ti faccio sapere.

zamak
21-12-2004, 15:40
per esattezza:
"This is perl, v5.8.3 built for i386-linux-thread-multi"

Quindi in perdoc all'indirizzo:
http://www.perldoc.com/perl5.8.4/pod/perlreref.html#OPERATORS
per la versione 5.8.4, dove si parla degli operatori (\i \s \m ...) si dice:
<< s match as a Single line - . matches \n >>

quindi come pensavo; allora perchè i seguenti risultati?

/\|$ref.?$/i # SI (ma per ogni carattere finale)
/\|$ref./is # NATURALMENTE SI (ma funzionerebbe per ogni carattere seguito da infiniti altri)
/\|$ref.$/is # NATURALMENTE SI (ma funz. con ogni carattere finale)

/\|$ref\n/is # NO
e per provarle tutte... (ma ne ho provate anche altre)
/\|$ref\n/im # NO
/\|$ref$/im # NO
/\|$ref\n$/im # NO

Risultato: :confused:

Mich_
21-12-2004, 15:56
Cosi` tanto per provare ... Mi e` venuto un dubbio: tu sai che caratteri ci sono nel tuo file?
Perche` il \n scritto da una macchina windows diventa \r\n in linux e di un mac diventa \r
\r = CR = 0x0D = 13. = ^M
\n = LF = 0x0A = 10. = ^J

Quando ho dubbi io uso questo:
print &ascii($str)."\n";

dove la funzione ascii e`:

sub ascii { # ritorna codice ascii di tutta la stringa
# questa funzione e` utile solo nelle prove
$_ = shift; # stringa da convertire
my $ret = '';
while(length) {
$ret .= ord($_).' ';
$_ = substr($_, 1);
}
return $ret;
}

zamak
21-12-2004, 16:38
Ottima idea Mich_, hai fatto CENTRO!

mi ha fatto pensare al fatto che per fare i test, io scrivo il file a mano dal mio sistema Win e poi lo testo su linux.

ho usato il tuo Test Script con il file scritto a mano sotto Win con la seguente linea:

11111|aaaaa

Risultato indice ASCII:
49 49 49 49 49 49 49 49 49 49 124 97 97 97 97 97 97 97 97 97 97 13 10

dove 13 è CR e 10 è LF cioè \r\n (per fortuna mi hai dato le corrispondenze)

infatti in diversi test con le RE mi risultava la presenza di un altro carattere prima di \n ; infatti /\|$ref.\n/i Funziona!

Grazie 1000 davvero Mich_ !

Loading