2010-07-08 4 views
2

파이프로 구분 된 값의 문자열 ($psv이라고 함)이 있으면이 파이프로 분할하고 배열을 채울 수 있기를 원합니다. 그러나 문자열에는 이스케이프 처리 된 파이프 (\|)와 이스케이프 처리 된 이스케이프 (\\)가 포함될 수 있습니다. 둘 다 단순한 리터럴로 간주됩니다. 내가 마음에이 문제에 대한 몇 가지 솔루션이 있습니다이스케이프 시퀀스가 ​​포함 된 문자열의 순수 정규식 분할이 있습니까?

  • ,하지-그렇지 않으면 $psv, split(/\|/, $psv)에서 발견 어떤 임의의 문자열을 모두 이스케이프 시퀀스를 교체 $psv을 통해 원래의 문자를
  • 루프를 다시 교체를 문자 부산물 문자

그리고 둘 다 작동한다고 생각합니다. 하지만 최대 도파민 홍수에 대해서, 나는 하나의 split() 전화만으로이 일을하고 싶습니다. 이것에 대한 정규 표현식이 있습니까?

답변

2

,이 같은 것을 함께 할 수있을 것 :의 (홀수 앞에되지 않은 파이프 문자와 일치해야합니다

split(/(?<!(?<!\\)(?:\\\\)*\\)\|/, $psv); 

백 슬래시 앞에 백 슬래시가 없음). 그러나 고정 너비 룩 어 헤드 어설 션만 허용되므로 옵션이 아닙니다. 일부 정규 표현식 전문가가 실제로 당신을 위해 일할 수있는 뭔가를 생각해 낼 수도 있지만, 개인적으로는 유한 상태 기계 (한 번에 한 문자 씩 $psv 반복)가 더 나은 옵션 일 수 있다고 말하고 싶습니다.

시도해 볼 수있는 다른 방법은 파이프 문자에서 문자열을 분할 한 다음 결과 목록의 각 요소를 검사하여 홀수 번째의 백 슬래시로 끝나는 지 확인하는 것입니다. 일치하는 경우 목록의 다음 요소 인 요소에 |을 다시 가입시킵니다. 기본적으로 이스케이프 시퀀스를 무시한 분할을 수행 한 다음 나중에 돌아가서 이스케이프를 고려합니다.

+0

"아니,하지만 여기에 하나의 추가 기능이 주어지면 그러한 정규 표현식이 어떻게 생겼는지가 중요합니다"라고 가정합니다. –

+0

짝수 번호의 이스케이프를 허용하고 홀수로 거부하는 방식으로 번갈아 가며 접근 할 수 있습니다. – tchrist

+0

@ RichardSimões 당신은이 답변을 사용할 수 있습니다 : http://stackoverflow.com/questions/8445634/php-regex-split-on-unescaped-delimiter - 역순으로 작동합니다. 단락 기호를 분리하는 대신 구분 기호가 아닌 것을 캡처합니다 . – Ariel

4

이 작업에는 split을 사용할 필요가 없습니다. 대안은 다음과 같습니다.

my $psv = "aaa|bbb||ccc|\\|\\|\\||\\\\\\\\\\\\"; 
print "$psv\n"; 

my @words = map { s/\\([\\|])/$1/g; $_; } ($psv =~ /(?:^|\|) ((?:\\[\\|] | [^|])*)/gx); 
printf("%s\n", join(", ", @words)); 

정규식은 무서워 보일 수 있지만 쉽게 설명 할 수 있습니다. 파이프로 구분 된 각 단어와 일치합니다. 문자열의 시작 부분이나 파이프 분리 문자로 시작합니다. 그런 다음 임의의 수의 이스케이프 시퀀스 (\ + \| 중 하나) 또는 파이프를 제외한 임의의 문자를 따릅니다.

map의 정규 표현식은 실제로 의미하는대로 이스케이프 시퀀스를 대체합니다. 펄은 가변 폭 보이는 숨김 주장을 지원하는 경우

+0

난 당신의 솔루션을 보지 않았다, 그러나 우리는 유사한 정규식의가 있습니다. 일부는 ikegami @ perlmonks.org에서 정규 표현식 디버깅을 제공합니다. – vol7ron

4

순수 정규식 솔루션이 필요한 특별한 이유가 있습니까? (이 질문이 정신적 도전에 더 가깝지 만 실용적인 문제가 아니라면).

실제 코드에서 X로 구분 된 데이터를 처리하는 올바른 방법은 올바른 파서를 사용하는 것입니다. 매우 일반적인 방법은 Text::CSV_XS입니다 (이름을 속일 수 없으므로 쉼표 만 사용할 수 있습니다) . 인용 부호와 함께 이스케이프를 올바르게 처리합니다.

0

단맛 솔루션

이 방법은 분할을 사용하지 않고, 간단한 정규식을 사용 않습니다.


#!/usr/bin/perl -w 

use strict; 

    sub main{ 
     (my $psv = <DATA>) =~ s/\s+$//s; 

     my @arr = $psv =~ /(?:^|\G\|)((?:[^\\|]|\\.)*)/sg; 

     { 
     local $" = ', ';  # $" - sets the pretty print 
     print "@arr \n";  # outputs: abc, def, g\|i, jkl, m\|o, pqr, s\\u, v\w, x\\, , z 
     } 

    } 

    main(); 


__DATA__ 
abc|def|g\|i|jkl|m\|o|pqr|s\\u|v\w|x\\||z 
관련 문제