2009-08-11 2 views
4

동료를위한 Repost from Perlmonks :Perl의 분할 명령을 공백을 제거하는 것과 어떻게 조합 할 수 있습니까?

세미 콜론으로 구분 된 긴 이메일 목록을 구분하는 펄 스크립트를 작성했습니다. 이 코드로 수행하고자하는 작업은 두 개의 배열이 필요 없도록 분할을 공백 트리밍과 결합하는 것입니다. 첫 번째 배열을로드하는 동안 트리밍 할 수 있습니까? 출력은 정렬 된 이름 목록입니다. 감사합니다. .

#!/pw/prod/svr4/bin/perl 
use warnings; 
use strict; 

my $file_data = 
    'Builder, Bob ;Stein, Franklin MSW; Boop, Elizabeth PHD Cc: Bear, 
+ Izzy'; 
my @email_list; 

$file_data =~ s/CC:/;/ig; 
$file_data =~ s/PHD//ig; 
$file_data =~ s/MSW//ig; 

my @tmp_data = split(/;/, $file_data); 

foreach my $entry (@tmp_data) { 
    $entry =~ s/^[ \t]+|[ \t]+$//g; 
    push(@email_list, $entry); 
} 

foreach my $name (sort(@email_list)) { 
    print "$name \n"; 
} 
+2

시도해 보셨습니까? split/\ s *; \ s */$ file_data –

+0

unpack()을 사용할 수도 있지만 지금 당장은 시도 할 수 없으며 풀어서는 안됩니다(). 그것없이 당신에게 해결책을 제공합니다. – Makis

답변

10

동일한 기능을 사용하여 한 번에 두 가지 작업을 수행 할 필요는 없습니다. 때로는 별도로 작업을 수행하는 것이 더 명확해질 수 있습니다.

@email_list = 
    sort(
     map { 
       s/\s*(\S+)\s*/\1/; $_ 
      } 
      split ';', $file_data 
    ); 

EDIT : 동시에 스트링의 하나 개 이상의 부분을 스트리핑 함정 이어질 수, 예를 들어 이는 분할 제 다음 (그 결과를 다음 정렬) 오프 각 요소의 공백을 제거한다 "엘리자베스"부분에 후행 공백을 두는 것에 대한 신안의 요점. 나는 그 이름이 내부 공백을 갖지 않을 것이라는 가정하에 그 스 니펫을 코딩했는데, 이것은 실제로 틀린 것이며, 의식적으로 그것을 알아 차렸을 때 부정확 한 것처럼 보였을 것이다.

@email_list = 
    sort(
     map { 
       s/^\s+//; # strip leading spaces 
       s/\s+$//; # strip trailing spaces 
       $_   # return the modified string 
      } 
      split ';', $file_data 
    ); 
+0

분명히 주석에 공백이 여러 개있을 수는 없지만 * Elizabeth * 뒤에 공백이있을 수 있습니다. –

+0

> 첫 번째 ... 두 번째 ... 아주 좋은 점! 위의 수정 된 응답. – Ether

+0

+1 수정 해 주셔서 감사합니다. –

11

첫 번째와 마지막 요소를 트리밍 할 필요가없는 경우,이 트릭을 할 것입니다 :

@email_list = split /\s*;\s*/, $file_data; 

첫 번째와 마지막 요소를 트리밍해야하는 경우를 $file_data 먼저 트림, 위와 같이 반복하십시오. :-P

2

Chris가 제안한 것을 할 수는 있지만 $ file_data의 앞뒤 공백은 처리하지 못합니다.

이 같은 이들의 처리를 추가 할 수 있습니다

또한
$file_data =~ s/\A\s+|\s+\z//g; 

, 2 차 배열을 사용하는 것이 필요하지 것을 유의하시기 바랍니다. 이것을 확인하십시오 :

my $file_data = 'Builder, Bob ;Stein, Franklin MSW; Boop, Elizabeth PHD Cc: Bear, Izzy'; 
my @email_list; 

$file_data =~ s/CC:/;/ig; 
$file_data =~ s/PHD//ig; 
$file_data =~ s/MSW//ig; 

my @tmp_data = split(/;/, $file_data); 

foreach my $entry (@tmp_data) { 
    $entry =~ s/^[ \t]+|[ \t]+$//g; 
} 

foreach my $name (sort(@tmp_data)) { 
    print "$name \n"; 
} 
-1

일부 사소한 sintax 오류를 제외하고, 이것은 전체 작업을 수행해야합니다. 오, 목록 작업, 당신이 얼마나 아름다운 지!

print join (" \n", sort { $a <=> $b } map { s/^[ \t]+|[ \t]+$//g } split (/;/, $file_data)); 
+1

지도가 s /// 결과를 반환하는 것은 그리 유용하지 않습니다. map {s /...// g; $ _} – ysth

+0

아마도 숫자 정렬을 의미하지는 않습니다. – ysth

1
my @email_list = map { s/^[ \t]+|[ \t]+$//g; $_ } split /;/, $file_data; 

또는 더 우아한 :

use Algorithm::Loops "Filter"; 
my @email_list = Filter { s/^[ \t]+|[ \t]+$//g } split /;/, $file_data; 
0

내 차례 :

my @fields = grep { $_ } split m/\s*(?:;|^|$)\s*/, $record; 

는 또한 최초의 스트립 아래 코드는 훨씬 개선 (그리고 더 읽기)입니다 마지막 요소도 포함됩니다. grep 경우 첫 번째 요소를 제거하기 위해 과잉이다 :

my (undef, @fields) = split m/\s*(?:;|^|$)\s*/, $record; 

작품은 공간이 있음을 알고 경우,하지만

my @fields = split m/\s*(?:;|^|$)\s*/, $record; 
shift @fields unless $fields[0]; 

그렇게하지 가능성에 대한 가장 확실한 방법입니다 해.

1

FAQ의 How do I strip blank space from the beginning/end of a string?을 참조하십시오.지금

@email_list = sort map { 
    s/^\s+//; s/\s+$//; $_ 
} split ';', $file_data; 

, 참고도 for 루프 별명 어레이의 각 요소는, 그래서

@email_list = sort split ';', $file_data; 

for (@email_list) { 
    s/^\s+//; 
    s/\s+$//; 
} 

도 작동 것이다.

관련 문제