2010-05-18 2 views
2

경로에서 파일 이름을 구문 분석하려고합니다. 나는이 있습니다Perl 정규 표현식이 경로에서 파일 이름을 올바르게 추출하지 않는 이유는 무엇입니까?

my $filepath = "/Users/Eric/Documents/foldername/filename.pdf"; 
$filepath =~ m/^.*\\(.*[.].*)$/; 
print "Linux path:"; 
print $1 . "\n\n"; 
print "-------\n"; 

my $filepath = "c:\\Windows\eric\filename.pdf"; 
$filepath =~ m/^.*\\(.*[.].*)$/; 
print "Windows path:"; 
print $1 . "\n\n"; 
print "-------\n"; 

my $filepath = "filename.pdf"; 
$filepath =~ m/^.*\\(.*[.].*)$/; 
print "Without path:"; 
print $1 . "\n\n"; 
print "-------\n"; 

을하지만 그 반환

Linux path: 

------- 
Windows path:Windowsic 
         ilename.pdf 

------- 
Without path:Windowsic 
         ilename.pdf 

------- 

내가이 기대 오전 :

Linux path: 
filename.pdf 
------- 
Windows path: 
filename.pdf 
------- 
Without path: 
filename.pdf 
------- 

누군가가 내가 잘못 뭐하는 거지 지적시겠습니까?

감사합니다. :)

+1

디버깅의 트릭 중 하나는 작업하기 전에 작업중인 데이터를 인쇄하는 것입니다. 자신이 생각하는 것부터 시작하고 있는지 확인하고 싶습니다. –

답변

2

글쎄, 일어나는 일에 대한 대답은 다양한 오류입니다.

my $filepath = "/Users/Eric/Documents/foldername/filename.pdf"; 
$filepath =~ m/^.*\\(.*[.].*)$/; 
print "Linux path:"; 
print $1 . "\n\n"; 
print "-------\n"; 

$filepath는 어떠한 \\의를 가지고 있지 않기 때문에이 일치하고 더 $1 없다되지 않습니다. 당신은 /을 넣어. 귀하의 표현이 될 것이다 :

# regular expression matches return their captures in a list context. 
my ($path) = $filepath =~ m|/([^/.]*\.[^/.]*)$|; 
print "Linux path:$path\n\n-------\n"; # little need to . a " string 

my $filepath = "c:\\Windows\eric\filename.pdf"; 
$filepath =~ m/^.*\\(.*[.].*)$/; 
print "Windows path:"; 
print $1 . "\n\n"; 
print "-------\n"; 

당신은, UNIX 쉘에서 자신의 큐를 복용, 작은 따옴표 문자열을보다 더 활성화되어 따옴표를 사용하고 있습니다.이 역시 작동 펄이 창에 대한 '/'을 이해하기 때문에,

my $filepath = 'c:\Windows\eric\filename.pdf'; 

사실 (그러나 :

my $filepath = "c:\\Windows\\eric\\filename.pdf"; 

하거나 작은 따옴표를 사용 : 따라서,이 같은 모든 당신의 백 슬래시를 이스케이프 할 필요가 정규식의 경우)

my $filepath = "c:/Windows/eric/filename.pdf"; 

Windows로 다시 전달하기 전에 수정해야합니다.

my $filepath = "filename.pdf"; 
$filepath =~ m/^.*\\(.*[.].*)$/; 
print "Without path:"; 
print $1 . "\n\n"; 
print "-------\n"; 

이 너무 $1 여전히 마지막 일치하지 경기했다. 그것이 반복되는 이유입니다. 그러나 이것은 $1을 참조하는 대신 캡처를 포착하는 가치를 나타냅니다.

+0

모든 오류를 지적 해 주셔서 감사합니다. 이것이 제가 찾고 있던 것입니다. :) –

+0

Axeman, 다음 항목을 볼 수 있습니까? 끝에있는 $ 이름이 인쇄되지 않습니다. 이것이 바로이 문제를 해결하는 마지막 문제입니다. 감사! :) –

4

File::Basename을 사용하지 않으시겠습니까?

$name = basename($filepath) 
print $name 

정규식

m/^.*\\(.*[.].*)$/ 
# ^^ 

는 세퍼레이터 \ 때문에, 케이스 (1)을 가정하고 3과 일치하지 않을 것이다. 경우 2에서

"c:\\Windows\eric\filename.pdf"; 

\e\f는 펄에서 모두 특수 문자입니다. 따라서 코드 "exactly"는 Windows\eric\filename.pdf을 파일 이름으로 반환합니다. \\을 반드시 사용하십시오!

+0

Kenny에게 감사드립니다. File :: Basename을 살펴보고 먼저이 작업을 수행하려고합니다. :) –

+0

왜 시간 낭비 할 필요가 있습니까? 지금 일하는 것을 사용하고 인생에서 전진하십시오. –

3

펄이 기능을 제공합니다 http://perldoc.perl.org/File/Basename.html

또한 문자열을 경계 할 필요가 탈출 - 윈도우 경로 문자열이 '\', '\ f를'및 '\ 전자'에 빠져되고있다 - 그것은이었다 동안 나는 펄 탈출을 다뤘지만, 나는 또한 그 후에 'r'을 삼키고 있다고 추측하고있다. 이것은 예기치 않은 결과를 설명합니다.

+0

고맙습니다. 물론, \ f와 \ e는 문제가있었습니다. –

7

다른 사람들이 말했듯이, 실수는 직접하는 것입니다.

File::Basename 외에도 File::SpecPath::Class을 살펴 봐야합니다. 이들은 파일과 디렉토리를 처리하기 위해 잘 테스트 된 크로스 플랫폼 방식을 제공합니다. Path::Class은 특히 스크립트가 살아있는 시스템에 대해 외부인 파일 및 디렉토리 이름을 다루는 데 도움이되는 방법을 제공합니다. 그것은 그것이 여기에 편리하게 들어올 수있는 것처럼 보입니다.

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Path::Class qw/file foreign_file/; 

my $nix = "/Users/Eric/Documents/foldername/filename.pdf"; 
my $win = 'c:\\Windows\eric\filename.pdf'; # single quote to avoid escape issues 

print file($nix)->basename(), "\n"; 
print foreign_file('Win32', $win)->basename(), "\n"; 
관련 문제