2015-07-13 3 views
6

Perl (< v5.18) Regulärer Ausdruck Zeichenklasse \s für Whitespace ist identisch mit [\t\n\f\r ].Wie man s neu definiert, um Unterstriche zu treffen?

Jetzt, da einige Dateinamen Unterstriche als Leerzeichen verwenden, habe ich mich gefragt, ob es möglich ist, \s (lokal) neu zu definieren, um Unterstrichen zusätzlich zu Leerzeichen zu entsprechen.

Dies wäre nur aus Gründen der Lesbarkeit ansonsten gefalteter regulärer Ausdrücke mit vielen [\s_]. Darf ich das machen? Wenn das so ist, wie?

+1

Speichern Sie die Regex in einer Variablen mit 'qr' – toolic

+14

IMHO, die Änderung der Bedeutung von \ s zu stillen verhalten in einer nicht standardmäßigen Weise würde Lesbarkeit schaden, nicht verbessern. Selbst wenn Sie dies eindeutig in den Kommentaren dokumentieren, muss jeder, der Ihren Code liest, daran denken, dass er jedes Mal, wenn er \ s sieht, ihn mental durch [\ s_] ersetzen muss. – plasticinsect

+6

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

Antwort

12

Immer wenn ich denke, dass etwas in Perl unmöglich ist, stellt sich heraus, dass ich falsch liege. Und manchmal, wenn ich denke, dass etwas in Perl sehr schwierig ist, liege ich auch falsch. @sln wies mich auf die right track

Lassen Sie uns noch nicht \s überschreiben, obwohl Sie könnten. Für die Erben Ihres Programms, die erwarten, dass \s etwas Bestimmtes bedeutet, definieren wir stattdessen die Sequenz \_ als "beliebiges Leerzeichen" oder "_" in einem regulären Ausdruck. Die Details sind in dem obigen Link, aber die Umsetzung wie folgt aussieht:

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; 

Jetzt in Ihrem Skript, sagen

use myspace; 

und jetzt \_ in einem regulären Ausdruck bedeutet [\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 

Ausgang:

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

Der dritte Fall ist es zu zeigen, dass \\_ in einem regulären Ausdruck wird eine wörtliche \_ übereinstimmen, wie \\s eine wörtliche \s entsprechen.

+2

Niemand benutzt heutzutage myspace ... :) – simbabque

Verwandte Themen