2008-10-08 3 views
11

한 줄에이 작업을 수행 할 수있는 방법이 있습니까?문자열의 양쪽에서 공백을 제거하기위한 Perl 호환 정규 표현식이 있습니까?

$x =~ s/^\s+//; 
$x =~ s/\s+$//; 

즉, 문자열에서 모든 앞뒤 공백을 제거하십시오. 여기

+2

"trim"은 문자열의 양쪽에서 whitepsace를 제거하기위한 일반 이름입니다. 당신은 할 수 있습니다 : $ title = ~ s/remove/trim/ – Kip

+0

"pcre"태그는 C 정규 표현식 라이브러리 (PHP의 preg 기능을 지원하는 라이브러리)의 이름이기 때문에 제거하고 있습니다. 이리. –

답변

26
$x =~ s/^\s+|\s+$//g; 

또는

s/^\s+//, s/\s+$// for $x; 
+0

옵션 2 : 좋은 트릭이지만, 실제로 질문에 대답하지 않습니다 : D – ephemient

+2

어떻게 그 질문에 대답하지 않습니까? 그것은 하나의 정규식의 성능을 빨아 들이지 않으면 서 양쪽에서 트리밍됩니다. –

+0

s/^ \ s * (. *?) \ s */\ 1 /; 이 두 옵션 중 하나보다 더 많은 대안을 시도해야합니다. –

4

당신은 갈 : $x =~ s/\A\s*(.*?)\s*\z/$1/;

2

$ X = ~ S/(^ \ S +) | (\ S + $) // g;

+1

그것이 내가 항상하는 방법입니다. .. 훨씬 쉬운 것 같습니다. – Kip

+0

예, 그리고 그것이 의미하는 바를 말합니다 - 시작 공백을 대체하거나 공백을 공백으로 대체하십시오. –

+2

캡처 괄호는 사용되지 않거나 필요하지 않습니다 - 일반적으로 그룹화 괄호 (? : ...)로 대체 할 수 있지만이 경우 우선 순위가 제대로 작동하고 괄호를 모두 제거 할 수 있습니다. – ephemient

-2
$x =~ s/^\s*(.*?)\s*$/$1/; 
+0

대체 문자열에서 $ 1 대신 \ 1을 쓰는 것은 Perl에서는 권장하지 않습니다. perldoc perlre에서 "Warning on \ 1 vs $ 1"을 참조하십시오. – ephemient

+0

수량 한정자는 욕심이 많으므로 \ s +를 찾은 후에 [^ \ s]와 (과) 같이 말할 필요가 없습니다. 또한 [^ \ s] 대신 \ S 만 말할 수 있습니다. 대문자로 된 버전은 보충 된 문자 클래스입니다. :) –

+0

브라이언 : 예,하지만. * 유령을 만들 경우에만. – Lev

0
s/^\s*(\S*\S)\s*$/$1/ 
+0

대체 문자열에서 $ 1 대신 \ 1을 쓰는 것은 Perl에서는 권장하지 않습니다. perldoc perlre에서 "Warning on \ 1 vs $ 1"을 참조하십시오. – ephemient

+0

네 말이 맞아, 내가 바로 잡을거야. –

+0

여기서 문제는 문자열에 공백이 아닌 문자가 2 개 이상 필요합니다. 그렇지 않으면 작동하지 않습니다. – bart

30

내 첫 번째 질문은 ... 왜? 나는 당신이 시작한 정규 표현식보다 더 읽을 수있는 단일 정규 표현식 솔루션을 보지 못했습니다. 그리고 그들은 확실히 빨리 가까운 곳이 아닙니다.

#!/usr/bin/perl 

use strict; 
use warnings; 

use Benchmark qw(:all); 

my $a = 'a' x 1_000; 

my @x = (
     " $a ", 
     "$a ", 
     $a, 
     " $a" 
     ); 

cmpthese(-5, 
     { 
      single => sub { 
       for my $s (@x) 
       { 
        my $x = $s; 
        $x =~ s/^\s+|\s+$//g; 
       } 
      }, 
      double => sub { 
       for my $s (@x) 
       { 
        my $x = $s; 
        $x =~ s/^\s+//; 
        $x =~ s/\s+$//; 
       } 
      }, 
      trick => sub { 
       for my $s (@x) 
       { 
        my $x = $s; 
        s/^\s+//, s/\s+$// for $x; 
       } 
      }, 
      capture => sub { 
       for my $s (@x) 
       { 
        my $x = $s; 
        $x =~ s/\A\s*(.*?)\s*\z/$1/ 
       } 
      }, 
      kramercap => sub { 
       for my $s (@x) 
       { 
        my $x = $s; 
        ($x) = $x =~ /^\s*(.*?)\s*$/ 
       } 
      }, 
     } 
     ); 

는 내 컴퓨터에 결과를 제공합니다 :

 
      Rate single capture kramercap  trick double 
single  2541/s  --  -12%  -13%  -96%  -96% 
capture 2902/s  14%  --  -0%  -95%  -96% 
kramercap 2911/s  15%  0%  --  -95%  -96% 
trick  60381/s  2276%  1981%  1974%  --  -7% 
double 65162/s  2464%  2145%  2138%  8%  -- 

편집 : runrig를 잘하지만, 약간의 변화. 난 수정하기 전에 문자열을 복사하는 코드를 업데이트했습니다. 물론, 속도가 느려집니다. 또한 긴 문자열을 사용하는 또 다른 대답으로 브라이언 디 포이 (Brian d foy)의 제안을 고려했습니다 (백만 명이 지나치게 많았 음). 그러나 그것은 또한 트릭 스타일을 선택하기 전에 문자열 길이가 어떤 것인지 파악합니다. 즉, 짧은 문자열로 트릭의 이점을 줄입니다. 모든 길이에서 나는 더블 우승을 테스트했습니다. 그리고 눈에 아직도 더 쉽습니다.

+0

당신은 Perl에서이 작업을하고 있다고 가정하고 있습니다. "Perl 호환"은 항상 나를 위해 적기를 일으킨다. –

+0

True - perl과 pcre 태그 모두를 보는 것이 약간 혼란 스럽습니다 ... – Tanktalus

+0

모든 "테스트"가 첫 번째 반복에서 @x를 변경합니다. 그래서 당신이 생각하는 것을 테스트하는 사람은 아무도 없습니다. 서브 시스템에서 @x를 복사해야합니다. 그리고 이중 해결책에서 그것을 for 루프로 감싸지 말고, "for @x"를 사용하십시오. – runrig

5

이교도의 이의 제기에 대해 전혀 생각하지 않으시겠습니까? 위의 모든 해결책은 한 번에 문자열의 양쪽에서 공백을 제거하지만 끔찍하게 읽을 수있는 것은 없습니다 (어쩌면 this one). 코드의 대상이 전문가 수준의 Perl 코더로 구성되어 있지 않으면 위의 각 후보자는 자신이하는 일에 대해 설명하는 주석을 달아야합니다 (어쨌든 좋은 아이디어 일 것입니다). 이와는 대조적으로,이 두 라인은 보통 경험의 프로그래머 즉시 명확하지 않다 lookaheads, 와일드 카드, midichlorines 또는 아무것도를 사용하지 않고 같은 일을 수행 :

$string =~ s/^\s+//; 
$string =~ s/\s+$//; 

(틀림없이) 성능 저하하지만, 등이있다 실행 시간이 수 마이크로 초에 이르지 않는 한 오랫동안 추가 된 가독성은 그만한 가치가 있습니다. IMHO.

+0

실적이 좋습니까? 누가 그것을 주장 할 수 있습니까? 다른 솔루션보다 두 배 이상 빠릅니다. – Tanktalus

+0

충분히 (아주) 늦은 점심 식사를하기 위해 문을 나가기를 원했기 때문에 나는 코드를 벤치 마크하지 않았습니다. 다행히도 성능에 문제가 없음을 알고 기뻐하십시오. – Logan

+0

Perl 전문가입니까? 내 Learning Perl 과정에있는 사람들은 둘째 날이 끝날 때까지 모든 솔루션을 이해합니다. –

8

Tanktalus는 매우 작은 문자열에 대한 벤치 마크를 보여 주지만 문자열이 커짐에 따라 문제가 악화됩니다.

my $a = 'a' x 1_000_000; 

my @x = (
    " $a ", 
    "$a ", 
    $a, 
    " $a" 
); 

나는 이러한 결과를 얻을 : 자신의 코드에서, 나는 상단 부분을 변경 한 문자열은 "속임수"와 "더블"거의 동일하고,을 사용하여, 더 큰 얻을

  Rate single capture trick double 
single 2.09/s  -- -12% -98% -98% 
capture 2.37/s  13%  -- -98% -98% 
trick 96.0/s 4491% 3948%  --  -0% 
double 96.4/s 4512% 3967%  0%  -- 

으로 대부분의 사람들이가는 일반적인 해결책, "싱글"(나는 이것을 알고 있지만 그 습관을 깨뜨릴 수 없기 때문에 나를 포함해서)은 정말로 빨기 시작합니다.

벤치 마크를 볼 때마다 그것이 무엇을 말하고 있는지 생각해보십시오. 이해했는지 확인하려면 데이터를 변경하고 다시 시도하십시오. 배열을 길게, 스칼라를 크게, 등등으로 만듭니다. 루프, greps 또는 regexes가 시작, 중간 및 끝에서 물건을 찾습니다. 새로운 결과가 귀하의 예측과 일치하는지 확인하십시오. 추세가 무엇인지 파악하십시오. 성과가 더 좋아지고, 한계에 다 다르고, 최고점에 도달 한 후 하락하기 시작합니까? 아니면 다른 것입니까?

1

나는 보통 이런 식을 수행하십시오 선행 공백과 후행 공백 사이

($foo) = $foo =~ /^\s*(.*?)\s*$/; 

모든 그룹화 및 반환, 그래서 나는 예전의 변수에 할당 할 수있다.

-1
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/; 
관련 문제