2012-04-06 4 views
1

Ich habePattern Match auf/xxx/xxx/xxx

$w="/fold1/fold2/qwerty.h" 

Ich möchte schneiden /qwerty.h und erhalten/fold1/fold2

Ich versuchte

$w=~s/\/.+\.h\z//; and $w=~s/\/.+?\.h\z//; 

aber diejenigen, Entferne die ganze Zeichenfolge.

$w=~s/\/\w+\.h\z//; 

funktioniert, aber angenommen, ich habe qwe \ rty.h anstelle von qwerty.h. Das wird nicht wieder funktionieren.

+9

http://perldoc.perl.org/File/Basename.html – Mat

+3

Können Sie das Modul File :: Basename verwenden? –

+0

Wenn ich mich mit Mustern befasse, die einen Schrägstrich enthalten, verwende ich gerne {}, um [lehnendes Zahnstocher-Syndrom] zu vermeiden (http://en.wikipedia.org/wiki/Leaning_toothpick_syndrome#Pattern_example). So würde 'm/foo \/bar /' 'm {foo/bar}'. Ebenso würde 's/foo \/bar/qux \/baz /' zu 's {foo/bar} {qux/baz}'. Das kann fast alles sein: 'm! Foo! ist auch erlaubt. Wenn das Trennzeichen Teil eines Öffnen/Schließen-Paares ist, wird dieses Paar verwendet. Dies ist dokumentiert in [perlretut] (http://perldoc.perl.org/perlretut.html#Simple-word-matching). –

Antwort

1

Denken Sie darüber nach, was Sie tun; Sie sollten nach dem letzten /, so dass Ihr Muster auf /, nicht „alle Zeichen“ (.) oder „Wortzeichen“ (\w)

$w =~ s/\/[^\/]+\.h\z//; 

basieren zu entfernen, die mehr sauber geschrieben ist durch die Vermeidung von / als regex Separator:

$w =~ s,/[^/]+\.h\z,,; 

das heißt, File::Basename ist ein sauberer und im allgemeinen tragbare Lösung.

+0

hat funktioniert! Danke, was ist die Funktion von [] – woryzower

+0

'[]' ist eine Zeichenklasse, eine Gruppe von Zeichen, die alle übereinstimmen können (oder mit vorangestelltem '^' wie hier, jedes Zeichen * außer * die angegebenen). Hier passen wir alle Zeichen an, die kein '/' sind. – geekosaur

+0

danke ich habe die Idee – woryzower

7

Verwendung File::Basename, eines des Module in dem Standard Library:

use File::Basename; 
my $dir = dirname($path); 

Im Allgemeinen, wenn Sie wissen, dass die Daten eine bestimmte Art sind, versucht sie als diese Art zu behandeln. In diesem Fall wissen Sie, dass es sich um einen Dateipfad handelt. Anstatt ihn wie eine allgemeine Zeichenfolge zu behandeln, behandeln Sie ihn wie einen Dateipfad.

0

Wenn File::Basename nicht für Sie arbeiten, dann können Sie etwas tun:

substr($w, 0, rindex($w, '/')) 

ich diese verwenden, so oft, dass ich um diese mehrere Idiome haben:

sub rpos_of { 
    return unless 1 + (my $pos = rindex($_[0], $_[1])); 
    return $pos || '0E0'; 
} 
sub before_last { 
    return $_[0] unless my $pos = &rpos_of; 
    return substr($_[0], 0, $pos); 
} 
sub after_last { 
    return $_[0] unless my $pos = &rpos_of; 
    return substr($_[0], $pos + length($_[1])); 
} 
sub break_at_last { 
    return $_[0] unless my $pos = &rpos_of; 
    return (substr($_[0], 0, $pos) 
      , substr($_[0], $pos + length($_[1])) 
      ); 
} 
0
$w=~s#(.*)/[^/]+#\1# 

dies funktioniert auch, finde nur die endgültige /, und ersetzen Sie die ganze Zeichenfolge mit der Teilzeichenfolge vor dem endgültigen/