2014-12-22 2 views
2

입력 문자열이 key:"value",key2:"value"의 형식을 취하는 키 - 값 파서를 만들고 있습니다. 키에는 a-z, A-Z0-9 문자가 포함될 수 있으며 값에는 임의 문자가 포함될 수 있지만 :, ,, "\에는 백 슬래시가 필요합니다. 쉼표는 키 - 값 쌍을 분리하는 데 사용되지만 마지막 쌍 이후에는 필요하지 않습니다.일치하는 키 - 값 패턴 정규식

지금까지 대부분의 키와 값과 일치하는 ([a-zA-Z0-9]+):"(.*)"이 있지만 분명히 한 쌍 이상을 처리 할 수 ​​없거나 '제어'문자 중 하나가 이스케이프 처리되지 않는 경우는 분명 없습니다. (?<=\\)[:,"\\]은 이스케이프 된 모든 문자와 일치하는 것으로 보이지만 '정상'문자와 일치하지 않습니다.

쉼표 분리를 확인하고 이스케이프 처리 된 모든 '제어'문자 및 일반 문자를 일치시키는 방법이 있습니까? 이것은 정규식없이 구현하는 것이 더 낫겠습니까? 아니면 순차적으로 여러 패턴이 필요합니까?

몇 가지 예 :

입력 : joe:"bread",sam:"fish" 출력 : joe -> breadsam -> fish

입력 : joe:"Look over there\, it's a shark!",sam:"I like fish." 출력 : joe -> Look over there, it's a shark!sam -> I like fish

+0

예상 결과와 함께 예제를 제공 할 수 있습니까? –

+0

왜'input_string.split (",")'을 사용하지 않고 결과와'result.split (":")'을 반복하지 않으면 루프에서 원하는 키 -> 쌍을 찾을 수 있습니다. – gwillie

+0

새 행을 값의 일부로 포함 할 수 있습니까? 그리고 그 값에 어떻게 지정되어 있습니까? – nhahtdh

답변

1

줄 종결자를 제외한 모든 문자 앞에 오는 \이 바로 뒤에 오는 문자를 지정한다고 가정합니다.

당신은 키 - 값 쌍의 모든 인스턴스를 일치하도록 다음과 같은 정규식을 사용할 수 있습니다

"([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\"" 

\\s*을 추가하고 : 후 당신은 무료로 간격을 허용 할 경우.

([a-zA-Z0-9]+):"((?:[^\\"]|\\.)*+)" 

은 정량 *는 2 가지 [^\\"]\\. 독점 상호 때문에 (어떤 문자열이 두 가지를 동시에 일치 할 수 없습니다), 소유 *+을 만들어 :

는 정규식 엔진이 보는 것입니다 . 또한 Pattern 클래스의 오라클 구현에서 StackOverflowError을 피할 수 있습니다. ( \n\uhhhh\xhh, \0는 예를 들면), 별도의 쓰기 할 수 있습니다 이스케이프 시퀀스의 복잡성에 따라,

Pattern keyValuePattern = Pattern.compile("([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\""); 
Matcher matcher = keyValuePattern.matcher(inputString); 

while (matcher.find()) { 
    String key = matcher.group(1); 

    // Process the escape sequences in the value string 
    String value = matcher.group(2).replaceAll("\\\\(.)", "$1"); 

    // ... 
} 

일반적인 경우 :

는 정규 루프에서 위의 정규식을 사용하여 함수를 사용하여 구문 분석합니다. 그러나, 위의 가정으로, 한 - 라이너 충분합니다.

이 해결 방법은 분리 기호에 대해서는 신경 쓰지 않습니다. 가장 가까운 일치 항목에 대한 잘못된 입력은 건너 뜁니다.

abc:"xyz:"text text", more:"pair" 
이 동작이 바람직하지 않은 경우

, 해결책이 있지만, 아래 잘못된 입력의 예에서,이 솔루션은 위의 키 - 값 쌍으로 xyz:"text text" AMD more:"pair" 일치 행복하게 시작 부분에 abc:"을 건너 뛰고 것

"(?:^|(?!^)\\G,)([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\"" 

자유 간격 버전 :

모든 키 - 값 쌍을 포함하는 문자열 대신 키 - 값 쌍과 아무 상관이없는 더 큰 문자열의 일부가되는, 첫째 격리해야
"(?:^\s*|(?!^)\\G\s*,\s*)([a-zA-Z0-9]+)\s*:\s*\"((?:[^\\\\\"]|\\\\.)*+)\"" 
+0

키 - 값 쌍으로 문자열을 분할 한 다음 '^ ([a-zA-Z0-9] +) :((? : \ \ [: \\,] | [^ : "\\,]) *)"$ "귀하의 답변에 감사드립니다. 처음으로 분할하면 문제가 발생하면 더 자세한 설명 오류를 줄 수 있습니다. 이것이 가장 효율적인 방법인지는 확실치 않지만, 내가 가지고있는 모든 테스트 케이스에서 작동하고 잘못된 형식의 것을 거부하는 것으로 보인다. – user2248702

2

당신은 키 값 쌍을 얻기 위해 아래 정규식을 사용할 수 있습니다.

([a-zA-Z0-9]+):"(.*?)(?<!\\)" 

또는

([a-zA-Z0-9]+):"(.*?)"(?=,[a-zA-Z0-9]+:"|$) 

DEMO

자바 정규식

"([a-zA-Z0-9]+):\"(.*?)(?<!\\\\)\"" 

(?<!\\)" 부정적인 lookbehind은 큰 따옴표는 백 슬래시 문자 덧붙일되지 않습니다 주장 일 것이다. 자바에서 백 슬래시 문자를 일치하도록, 당신은 당신의 패턴에서 백 슬래시 정확히 세 번, 즉, \\\\

을 탈출 할 필요가

DEMO

String s = "joe:\"Look over there\\, it's a shark!\",sam:\"I like fish.\""; 

Matcher m = Pattern.compile("([a-zA-Z0-9]+):\"(.*?)(?<!\\\\)\"").matcher(s); 
    while(m.find()) 
    { 
     System.out.println(m.group(1) + " --> " + m.group(2)); 
    } 
} 

출력 :

joe --> Look over there\, it's a shark! 
sam --> I like fish. 

또는

String s = "joe:\"Look over there\\, i\\\"t's a shark!\",sam:\"I like fish.\""; 

Matcher m = Pattern.compile("([a-zA-Z0-9]+):\"((?:\\\\\"|[^\"])*)\"").matcher(s); 
    while(m.find()) 
    { 
     System.out.println(m.group(1) + " --> " + m.group(2)); 
    } 
} 

출력 :

joe --> Look over there\, i\"t's a shark! 
sam --> I like fish. 
+0

뒤에 쉼표가없는 문자열을 분리하기 위해'(? nhahtdh

+0

덧붙여서, 당신의 정규식은'abc : "값 \\"' – nhahtdh

+0

내 업데이트를 참조하십시오 ... –