2010-07-20 2 views
1

텍스트 파일을 구문 분석 중이며 아래에 표시된 형식으로 여러 줄을 가져옵니다.Perl에서 한 줄을 세 개의 세그먼트로 분할하는 정규식

그런 다음 세 줄로 분할하려고합니다. Part1 : sf; part2 : 이름; part3 : 방향.

하지만 이제 정규식을 작성하는 방법에 어려움이 있습니다. 내가 공백에 대한 분할에 대해 생각하고 새로운 문자열을 연결하는 배열을 사용했다 : 나는 S1,F11처럼 $ SF = S15,F49 // 다른 라인을 얻을 수있는 방법

S15,F49 Large Recipe Download Request (LRDR) S,H->E,reply 

my ($sf, $name, $direction) =~/I don't know how to implement here/ 

을; S6,F1; 기타

$ name = Large Recipe Download Request (LRDR) // 다른 $ sf의 다른 이름.

$ 방향 = S,H->E,reply; //이 3 편에 대한 하위 각 항목 사이에 공백이 없습니다 M,H<-E,reply 또는 S,H<->E 또는 S,H->E,[reply] 등 일부 시간 : $ 방향

+0

형식은 항상이 동일하게 유지 : 는 S15, F49 대형 레시피 다운로드 요청 (LRDR) S, H-> E는, 첫 번째 부분처럼 을 응답 할 것이다 쉼표 (,)를 포함하거나 두 번째 부분에 항상 대괄호()가 포함됩니까? –

+0

@Nikhil. 예, 저는이 선을 세 개의 세그먼트로 나누고 출력을 기반으로 XML 파일을 생성하려고합니다. –

답변

4

$sf 내에 공백이없는 경우 및

if ($subject =~ m/^(\S+)\s+(.*?)\s+(\S+)$/) { 
    $sf = $1; 
    $name = $2; 
    $direction = $3; 
} else { 
    // no match found 
} 

설명 :

$direction 항목, 당신은 각 라인에 다음 코드를 적용 할 수

^ : 문자열의 시작 부분에 정규식을 고정합니다.

(\S+) : 하나 이상의 공백이 아닌 문자를 찾습니다. 일치를 $1에서 캡처하십시오.

\s+ : 하나 이상의 공백 문자 (= 다음 항목의 구분 기호)와 일치하십시오. .

(.*?) : 몇 가지 가능한 여전히 전반적인 경기가 성공 할 수 있도록하고, $2에서 그 캡처로, 문자의 수를 일치 *

\s+(\S+) : 위의 유사 - 경기 공간 분리 (들) 및 비 공백 문자 ->$3.

$ : 문자열 끝에 검색 결과를 고정 시키십시오.


* 게으른 정량 *? 그 이유는 그렇지 않으면 정규 표현식의이 제품은 또한 마지막 하나를 제외한 모든 다음과 공간의 구분을 캡처하는 것입니다.

+1

처음에는 두 번째 그룹의 탐욕심 때문에 이것이 효과가 있을지 궁금했습니다. 그러나 마지막 그룹에 적어도 하나의 캐릭터가 필요하기 때문에 잘 작동합니다. 두 번째 그룹이 욕심이 많다면 좀 더 빨리 돌아 가야하기 때문에 조금 더 빨라질 수도 있지만 100 % 확실하지는 않습니다. 물론 이것은 마이크로 최적화 일 것이지만이 코드가 얼마나 자주 호출되는지 알지 못합니다. – musiKk

+0

나는 그것이 성능면에서 많은 차이를 만들지 않을 것이라고 생각합니다. 그러나 게으른 표현이나 욕심이 많은 표현을 사용하는지 여부에 따라 일치 결과가 달라집니다 (내 편집 참조). –

+0

아주 잘 작동합니다. –

2
my $str = "S15,F49 Large Recipe Download Request (LRDR) S,H->E,reply"; 

$str =~ /^([^\s]+) # sf: anything except whitespace until first whitespace 
      \s+ 
      (.+)  # name: anything 
      \s+ 
      ([^\s]+)$ # direction: anything except whitespace, from last 
        # whitespace to the end 
     /x; 
my ($sf, $name, $direction) = ($1, $2, $3); 
print $sf, "\n", $name, "\n", $direction, "\n"; 
1

당신이 보여 바로는,이 작동합니다 : 더 두 개 이상의 공백으로

my ($sf, $name, $direction) = split /\s{2,}/, $line; 

분할을.

이 의지 자동 씹는 : 주어진 라인의

my ($sf, $name, $direction) = split /\s{2,}|\n/, $line; 
+0

귀하의 분할 방법으로 구현하지 못했습니다. 자세한 내용은 링크를 참조하십시오. http://codepad.org/8n5b8pAd 내 랩톱에 경고 표시 (ActivePerl 5.10 사용) : $ direction을 연결 (.) 또는 D : \ learning \ perl \ nextLine.pl 줄의 초기화되지 않은 값으로 사용 , line 3 방향 = –

+0

붙여 넣기 사이트에는 하나의 탭이 있습니다. 이름과 방향 사이. 그래서 나는 정규식을'/ \ s {2,} | \ t | \ n /'로 바꾸고 내가 필요한 것을 얻었습니다. 귀하의 예를 들어, 당신은 3 공백이있었습니다. – Axeman

관련 문제