2012-12-12 3 views
1

나는 문자열이 있습니다
불규칙한 정규식 행동

$day = "11.08.2012 PROC BRE-AMS 08:00-12:00 (MIETWAGEN MIT BAK RES 6049687886) Y AMS-AMS 13:15-19:15" 

을 그리고 정규 표현식이 있습니다

$data = preg_split("/(?=[A-Z]{1,4}[\s]+[A-Z]{3}[\-][A-Z]{3}[\s]+)/", $day); 

(가) $data는 -array이 있어야 할 것으로 예상 :

array 
     0 => string '11.08.2012 ' (length=11) 
     1 => string 'PROC 08:00-12:00 (MIETWAGEN MIT BAK RES 6049687886) ' (length=22) 
     2 => string 'Y AMS-AMS 13:15-19:15' (length=21) 

하지만 내 결과 :

0 => string '11.08.2012 ' (length=11) 
     1 => string 'P' (length=1) 
     2 => string 'R' (length=1) 
     3 => string 'O' (length=1) 
     4 => string 'C BRE-AMS 08:00-12:00 (MIETWAGEN MIT BAK RES 6049687886) ' (length=59) 
     5 => string 'Y AMS-AMS 13:15-19:15' (length=21) 

여기서 일어나는 일을 되돌릴 수 없습니다. 누군가 pleaqse가 설명 할 수 있습니까?

+0

정규식 만들기/테스트 도구를 사용해 보셨습니까? –

답변

3

을 문제는 패턴의 (? = ...) 부분 표현이 위치 인과 일치한다는 것입니다. 나는 이것이 당신의 의도 였음을 이해합니다. 문제는 다음 일치가 (? =)에 지정된 패턴이 일치를 끝내지 않을 때 시작되지만 위치이 lookahead + 1 기호와 일치하는 것입니다.

자세한 내용을 확인해 보겠습니다. 이 별표로 표시 위치에 도착할 때까지 분할을 시도하는 첫 번째 시간, 그것은 문자열을 안내 : 그것은 주어진 패턴과 일치 할 수

11.08.2012 *PROC BRE-AMS 08:00-12:00 

을 .... 다음 시도를 들어, 하나 개의 심볼 시작 위치 '를 따라 범프', 이제 우리는 여기 :

11.08.2012 P*ROC BRE-AMS 08:00-12:00 

... 봐라, 우리는 다시 때문에 그 {1,4} 정량으로,이 패턴을 일치시킬 수 있습니다 ! 이것이 바로 '불규칙적 인'이 P, RO 기호입니다.


"해결 방법"부분은 설명입니다. 나는 가정이 중 가장 쉬운 방법은, 당신의 분할 패턴이 작은 트위스트를 추가 :

$data = preg_split('/\b(?=[A-Z]{1,4}\s+[A-Z]{3}-[A-Z]{3}\s+)/', $day); 
우리는 여전히 위치를 일치

-하지만 지금이 위치가에서 '단어'기호를 구분하는 것이어야한다 비 단어 하나. 같은 생각은 부정적인 lookbehind 패턴으로 표현 될 수있다 : 실제로 더 정확하지만, 덜 우아

$data = preg_split('/(?<![A-Z])(?=[A-Z]{1,4}\s+[A-Z]{3}-[A-Z]{3}\s+)/', $day); 

는 ..., 나는 가정한다.)

두 개의 측면도 : 1) 단일 기호 (- 또는 '바로 가기'하나 (예 : \s))를 지정해야 할 때 문자 클래스 구문을 사용하지 마십시오. 2) 작은 따옴표를 사용하여 일부 변수를 보간하지 않는 한 패턴을 구분합니다.

+0

일에 대한 제거 할 때 위대한 설명, 난 정말 어떻게 정규식 내부적으로 작동하는지 모르지만,이 설명은 가능한 한 명확하게 보여줍니다 :) – Paedow

2

하이픈은 문자 클래스의 메타 문자입니다. 하이픈을 문자 클래스에 포함 시키려면 백 슬래시로 이스케이프 처리해야합니다 (이 특별한 경우에는 문자 클래스가 하이픈 만 사용하기 때문에 작동합니다).

는 분할 문자열을 포함해야하는 경우 처음 1-4 문자 시퀀스의 첫 번째 문자가 테스트되도록, 단어 경계에 내다보기의 시작 앵커 : 한마디로

/(?=\b[A-Z]{1,4}\s+[A-Z]{3}-[A-Z]{3}\s+)/' 
+0

나는 괄호하고 "? ="스플리터가 결과 – Paedow

+0

에서 제거 될 것이며 내 편집 – Paedow

+0

포함되어 있기 때문에 내가 결과에 스플리터를 필요로 감사 –