2015-07-13 11 views
6

Perl (< v5.18) classe di caratteri di espressione regolare \s per spazi vuoti è uguale a [\t\n\f\r ].Come ridefinire s per abbinare i caratteri di sottolineatura?

Ora, poiché alcuni nomi di file utilizzano il carattere di sottolineatura come spazi, mi chiedevo se è possibile ridefinire \s (localmente) in modo che corrisponda ai caratteri di sottolineatura in aggiunta agli spazi bianchi.

Questo sarebbe semplicemente per motivi di leggibilità di espressioni regolari altrimenti contorte che hanno molti [\s_]. Posso farlo? Se é cosi, come?

+1

Memorizzare la regex in una variabile usando 'qr' – toolic

+14

IMHO, cambiando il significato di \ s per comportarsi in modo non standard in modo non standard danneggerebbe la leggibilità, non migliorarla. Anche se si documenta chiaramente nei commenti, è necessario che chiunque legga il proprio codice ricordi che ogni volta che vedono, devono sostituirlo mentalmente con [\ s_]. – plasticinsect

+6

'$ s = qr/[\ s _] /;' – ikegami

risposta

12

Ogni volta che penso che qualcosa in Perl sia impossibile, di solito si scopre che ho torto. E a volte, quando penso che qualcosa sia molto difficile in Perl, anch'io ho torto. @sln mi ha indirizzato allo right track

Non escludiamo ancora lo \s, sebbene sia possibile. Per gli eredi del tuo programma che si aspettano che \s significhi qualcosa di specifico, definiamo invece la sequenza \_ come "qualsiasi carattere di spazio bianco o il carattere _" all'interno di un'espressione regolare. I dettagli sono nel link qui sopra, ma l'implementazione sembra:

package myspace; # redefine \_ to mean [\s_] 
use overload; 
my %rules = ('\\' => '\\\\', '_' => qr/[\t\n\x{0B}\f\r _]/); 
sub import { 
    die if @_ > 1; 
    overload::constant 'qr' => sub { 
     my $re = shift; 
     $re =~ s{\\(\\|_)}{$rules{$1}}gse; 
     return $re; 
    }; 
} 
1; 

Ora nello script, dicono

use myspace; 

e ora \_ in un'espressione regolare significa [\s_].

Demo:

use myspace; 
while (<DATA>) { 
    chomp; 
    if ($_ =~ /aaa\s.*txt/) {  # match whitespace 
     print "match[1]: $_\n"; 
    } 
    if ($_ =~ /aaa\_.*txt/) {  # match [\s_] 
     print "match[2]: $_\n"; 
    } 
    if ($_ =~ /\\_/) {    # match literal '\_' 
     print "match[3]: $_\n"; 
    } 
} 
__DATA__ 
aaabbb.txt 
aaa\_ccc.txt 
cccaaa bbb.txt 
aaa_bbb.txt 

uscita:

match[3]: aaa\_ccc.txt 
match[1]: cccaaa bbb.txt 
match[2]: cccaaa bbb.txt 
match[2]: aaa_bbb.txt 

Il terzo caso è quello di dimostrare che \\_ in un'espressione regolare corrisponderà un letterale \_, come \\s corrisponderà un letterale \s.

+2

Nessuno utilizza myspace oggigiorno ... :) – simbabque

Problemi correlati