탈출 한 쉼표를 무시하는 동안 쉼표로 분리 된 문자열을 분할하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/820172

  •  03-07-2019
  •  | 
  •  

문제

추가 매개 변수 인 Escape Char를 얻는 StringUtils.commadelimitedListToStringArray 함수의 확장 버전을 작성해야합니다.

그래서 내 부르기 :

commaDelimitedListToStringArray("test,test\\,test\\,test,test", "\\")

반환해야합니다 :

["test", "test,test,test", "test"]



현재의 시도는 String.split ()를 사용하여 정규식을 사용하여 문자열을 분할하는 것입니다.

String[] array = str.split("[^\\\\],");

그러나 반환 된 배열은 다음과 같습니다.

["tes", "test\,test\,tes", "test"]

어떤 아이디어?

도움이 되었습니까?

해결책

정규 표현

[^\\],

"백 슬래시가 아닌 캐릭터와 쉼표가 뒤 따르는 캐릭터 일치"를 의미합니다. 이것이 바로 다음과 같은 패턴입니다. t, 일치하기 때문에 t 백 슬래시가 아닌 캐릭터입니다.

나는 당신이 일종의 사용이 필요하다고 생각합니다 부정적인 외모, 캡처하기 위해 , a \ 앞의 캐릭터를 캡처하지 않고도

(?<!\\),

(BTW, 나는 이것을 더 읽기 쉽게 만들기 위해 의도적으로 백 슬래시를 이중으로 이루어지지 않았다는 점에 유의하십시오)

다른 팁

노력하다:

String array[] = str.split("(?<!\\\\),");

기본적으로 이것은 쉼표가 두 개의 백 슬래시가 선행되는 경우를 제외하고는 쉼표에서 분할됩니다. 이것을 a라고합니다 부정적인 외관은 제로 폭의 주장입니다.

향후 참조를 위해 다음은 다음과 같은 완전한 방법입니다.

public static String[] commaDelimitedListToStringArray(String str, String escapeChar) {
    // these characters need to be escaped in a regular expression
    String regularExpressionSpecialChars = "/.*+?|()[]{}\\";

    String escapedEscapeChar = escapeChar;

    // if the escape char for our comma separated list needs to be escaped 
    // for the regular expression, escape it using the \ char
    if(regularExpressionSpecialChars.indexOf(escapeChar) != -1) 
        escapedEscapeChar = "\\" + escapeChar;

    // see http://stackoverflow.com/questions/820172/how-to-split-a-comma-separated-string-while-ignoring-escaped-commas
    String[] temp = str.split("(?<!" + escapedEscapeChar + "),", -1);

    // remove the escapeChar for the end result
    String[] result = new String[temp.length];
    for(int i=0; i<temp.length; i++) {
        result[i] = temp[i].replaceAll(escapedEscapeChar + ",", ",");
    }

    return result;
}

Matt B가 말했듯이 [^\\], 쉼표 앞의 캐릭터를 구분 기의 일부로 해석 할 것입니다.

"test\\\\\\,test\\\\,test\\,test,test"
  -(split)->
["test\\\\\\,test\\\\,test\\,tes" , "test"]

Drvdijk가 말했듯이 (?<!\\), 오해의 백 슬래시를 잘못 해석 할 것입니다.

"test\\\\\\,test\\\\,test\\,test,test"
  -(split)->
["test\\\\\\,test\\\\,test\\,test" , "test"]
  -(unescape commas)->
["test\\\\,test\\,test,test" , "test"]

나는 또한 등 슬래시를 탈출 할 수있을 것으로 기대합니다 ...

"test\\\\\\,test\\\\,test\\,test,test"
  -(split)->
["test\\\\\\,test\\\\" , "test\\,test" , "test"]
  -(unescape commas and backslashes)->
["test\\,test\\" , "test,test" , "test"]

Drvdijk가 제안했다 (?<=(?<!\\\\)(\\\\\\\\){0,100}), 최대 100 개의 백 슬래시로 끝나는 요소가있는 목록에 적합합니다. 이것은 충분히 ...하지만 왜 한도입니까? 더 효율적인 방법이 있습니까 (욕심이없는 것처럼 보이지 않습니까? 유효하지 않은 문자열은 어떻습니까?

나는 일반적인 솔루션을 위해 잠시 검색 한 다음 직접 썼다.

내 대답은 탈출 문자를 매개 변수로 받아들이지 않습니다.

public static List<String> commaDelimitedListStringToStringList(String list) {
    // Check the validity of the list
    // ex: "te\\st" is not valid, backslash should be escaped
    if (!list.matches("^(([^\\\\,]|\\\\,|\\\\\\\\)*(,|$))+")) {
        // Could also raise an exception
        return null;
    }
    // Matcher for the list elements
    Matcher matcher = Pattern
            .compile("(?<=(^|,))([^\\\\,]|\\\\,|\\\\\\\\)*(?=(,|$))")
            .matcher(list);
    ArrayList<String> result = new ArrayList<String>();
    while (matcher.find()) {
        // Unescape the list element
        result.add(matcher.group().replaceAll("\\\\([\\\\,])", "$1"));
    }
    return result;
}

패턴에 대한 설명 (Escaped) :

(?<=(^|,)) 앞으로 문자열의 시작 또는 a ,

([^\\,]|\\,|\\\\)* 구성된 요소 \,, \\ 또는 캐릭터는 아무것도 아닙니다 \ ...도 아니다 ,

(?=(,|$)) 뒤에는 문자열의 끝 또는 a가 있습니다 ,

패턴이 단순화 될 수 있습니다.

3 개의 파싱으로도 (matches + find + replaceAll),이 방법은 drvdijk가 제안한 방법보다 빠릅니다. 특정 파서를 작성하여 여전히 최적화 할 수 있습니다.

또한, 한 캐릭터 만 특별하면 탈출 캐릭터를 가질 필요가있는 것은 무엇입니까? 단순히 두 배가 될 수 있습니다 ...

public static List<String> commaDelimitedListStringToStringList2(String list) {
    if (!list.matches("^(([^,]|,,)*(,|$))+")) {
        return null;
    }
    Matcher matcher = Pattern.compile("(?<=(^|,))([^,]|,,)*(?=(,|$))")
                    .matcher(list);
    ArrayList<String> result = new ArrayList<String>();
    while (matcher.find()) {
        result.add(matcher.group().replaceAll(",,", ","));
    }
    return result;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top