정규식 용 Java API는 \s
공백과 일치 하는 상태입니다 . 따라서 정규식 \\s\\s
은 두 개의 공백과 일치해야합니다.
Pattern whitespace = Pattern.compile("\\s\\s");
matcher = whitespace.matcher(modLine);
while (matcher.find()) matcher.replaceAll(" ");
이것의 목적은 두 개의 연속 된 공백의 모든 인스턴스를 단일 공백으로 바꾸는 것입니다. 그러나 이것은 실제로 작동하지 않습니다.
정규식이나 “공백”이라는 용어에 대해 심각한 오해가 있습니까?
답변
예, 다음 결과를 가져와야합니다 matcher.replaceAll()
.
String result = matcher.replaceAll(" ");
System.out.println(result);
답변
UTS # 18의 RL1.2\s
를 충족하기 위해 반드시 필요한 경우에도 Java에서 고유 문자 집합의 공백을 일치시키기 위해 Java를 사용할 수 없습니다. Java는 유니 코드 공백 속성을 지원하지 않기 때문입니다 . 안타깝게도 표준을 준수하지 않습니다.
유니 코드는 26 개의 코드 포인트를 \p{White_Space}
다음 과 같이 정의합니다 . 그 중 20 개는 다양한 종류의 \pZ
GeneralCategory = Separator 이고 나머지 6 개는 \p{Cc}
GeneralCategory = Control 입니다.
공백은 매우 안정적인 속성이며 동일한 속성은 거의 영원히 존재했습니다. 그럼에도 불구하고 Java에는 이들에 대한 유니 코드 표준을 준수하는 속성이 없으므로 대신 다음과 같은 코드를 사용해야합니다.
String whitespace_chars = "" /* dummy empty string for homogeneity */
+ "\\u0009" // CHARACTER TABULATION
+ "\\u000A" // LINE FEED (LF)
+ "\\u000B" // LINE TABULATION
+ "\\u000C" // FORM FEED (FF)
+ "\\u000D" // CARRIAGE RETURN (CR)
+ "\\u0020" // SPACE
+ "\\u0085" // NEXT LINE (NEL)
+ "\\u00A0" // NO-BREAK SPACE
+ "\\u1680" // OGHAM SPACE MARK
+ "\\u180E" // MONGOLIAN VOWEL SEPARATOR
+ "\\u2000" // EN QUAD
+ "\\u2001" // EM QUAD
+ "\\u2002" // EN SPACE
+ "\\u2003" // EM SPACE
+ "\\u2004" // THREE-PER-EM SPACE
+ "\\u2005" // FOUR-PER-EM SPACE
+ "\\u2006" // SIX-PER-EM SPACE
+ "\\u2007" // FIGURE SPACE
+ "\\u2008" // PUNCTUATION SPACE
+ "\\u2009" // THIN SPACE
+ "\\u200A" // HAIR SPACE
+ "\\u2028" // LINE SEPARATOR
+ "\\u2029" // PARAGRAPH SEPARATOR
+ "\\u202F" // NARROW NO-BREAK SPACE
+ "\\u205F" // MEDIUM MATHEMATICAL SPACE
+ "\\u3000" // IDEOGRAPHIC SPACE
;
/* A \s that actually works for Java’s native character set: Unicode */
String whitespace_charclass = "[" + whitespace_chars + "]";
/* A \S that actually works for Java’s native character set: Unicode */
String not_whitespace_charclass = "[^" + whitespace_chars + "]";
이제 사용할 수 있습니다 whitespace_charclass + "+"
당신의 패턴으로 replaceAll
.
모든 것에 대해 죄송합니다. Java의 정규식은 고유 한 고유 문자 집합에서 잘 작동하지 않으므로 실제로 작동하도록하려면 이국적인 후프를 거쳐야합니다.
당신이 공백이 나쁜 생각한다면, 당신은 당신이 얻을 무엇을해야 볼 수 \w
및 \b
마지막으로 제대로 작동하도록!
예, 가능합니다. 그리고 예, 그것은 엉망진창입니다. 그것은 자선 활동입니다. 표준을 준수하는 Java 용 정규식 라이브러리를 얻는 가장 쉬운 방법은 ICU에 JNI를 사용하는 것입니다. OraSun은 측정하지 않기 때문에 Google이 Android에서하는 일입니다.
그렇게하고 싶지 않지만 여전히 Java를 고수하고 싶다면, 최소한 UTS 의 RL1.2a 요구 사항을 준수하기 위해 Java의 패턴을 “수정”하는 프런트 엔드 정규식 재 작성 라이브러리가 있습니다. # 18, 유니 코드 정규식 .
답변
Java의 경우 (php가 아니라 javascript가 아니라 기타) :
txt.replaceAll("\\p{javaSpaceChar}{2,}"," ")
답변
Regexbuddy (정규식 개발자 응용 프로그램) 포럼에 질문을 보냈을 때 \ s Java 질문에 대해 더 정확한 답변을 받았습니다.
“메시지 작성자 : Jan Goyvaerts
Java에서 \ s, \ d 및 \ w는 ASCII 문자 만 포함합니다. … 이것은 Java의 버그가 아니라 정규 표현식으로 작업 할 때 알아야 할 많은 것 중 하나입니다. 모든 유니 코드 공백과 줄 바꿈을 일치 시키려면 Java에서 [\ s \ p {Z}]를 사용할 수 있습니다. RegexBuddy는 아직 \ p {javaSpaceChar} ([\ s \ p {Z}]와 정확히 동일한 문자와 일치)와 같은 Java 관련 속성을 지원하지 않습니다.
… \ s \ s는 입력이 ASCII 전용 인 경우 두 개의 공백과 일치합니다. 진짜 문제는 그 질문에 받아 들여진 대답이 지적한 것처럼 OP의 코드에 있습니다. “
답변
나를 위해 일하는 것 같습니다.
String s = " a b c";
System.out.println("\"" + s.replaceAll("\\s\\s", " ") + "\"");
인쇄됩니다 :
" a b c"
코드 대신 이것을 의도했다고 생각합니다.
Pattern whitespace = Pattern.compile("\\s\\s");
Matcher matcher = whitespace.matcher(s);
String result = "";
if (matcher.find()) {
result = matcher.replaceAll(" ");
}
System.out.println(result);
답변
목적을 위해 다음 스 니펫을 사용할 수 있습니다.
import org.apache.commons.lang3.StringUtils;
StringUtils.normalizeSpace(string);
이렇게하면 간격이 단일로 정규화되고 시작 및 후행 공백도 제거됩니다.
String sampleString = "Hello world!";
sampleString.replaceAll("\\s{2}", " "); // replaces exactly two consecutive spaces
sampleString.replaceAll("\\s{2,}", " "); // replaces two or more consecutive white spaces
답변
Pattern whitespace = Pattern.compile("\\s\\s");
matcher = whitespace.matcher(modLine);
boolean flag = true;
while(flag)
{
//Update your original search text with the result of the replace
modLine = matcher.replaceAll(" ");
//reset matcher to look at this "new" text
matcher = whitespace.matcher(modLine);
//search again ... and if no match , set flag to false to exit, else run again
if(!matcher.find())
{
flag = false;
}
}