1 回答

TA貢獻1798條經驗 獲得超3個贊
您可以收集所有重復的單詞,然后在它們前面加上_:
// Java 9+
String s = "This is a test\nAnd this is also a test\nAnd these are also tests\ntest\nЭто тест\nЭто также тест\nИ это также тесты";
String rx = "(?sU)\\b(\\w+)\\b(?=.*\\b\\1\\b)";
String[] results = Pattern.compile(rx).matcher(s).results().map(MatchResult::group).toArray(String[]::new);
System.out.println(s.replaceAll("(?U)\\b(?:" + String.join("|", results) + ")\\b", "_$0"));
// Java 8
String s = "This is a test\nAnd this is also a test\nAnd these are also tests\ntest\nЭто тест\nЭто также тест\nИ это также тесты";
String rx = "(?sU)\\b(\\w+)\\b(?=.*\\b\\1\\b)";
List<String> matches = new ArrayList<>();
Matcher m = Pattern.compile(rx).matcher(s);
while (m.find()) {
matches.add(m.group());
}
System.out.println(s.replaceAll("(?U)\\b(?:" + String.join("|", matches) + ")\\b", "_$0"));
請參閱在線 Java 演示和第二個片段演示。輸出:
This _is _a _test
_And this _is _also a _test
And these are _also tests
test
_Это _тест
_Это _также тест
И это _также тесты
注意,我用與 DOTALL 嵌入標志選項組合替換了[\s\S]
解決方法構造(這樣也可以匹配換行符),使用 Java 9+方法返回所有匹配項,并根據與OR 交替運算符連接的找到的匹配項構建最終模式。.
s
.
.results()
|
細節
(?sU)\b(\w+)\b(?=.*\b\1\b)
:(?sU)
- 嵌入的 DOTALL (.
也使匹配換行符)和 UNICODE_CHARACTER_CLASS (使所有速記 Unicode 感知)標志選項\b
- 字邊界(\w+)
- 第 1 組:1+ 個單詞、字符、字母、數字或_
s\b
- 字邊界(?=.*\b\1\b)
- 緊鄰右側,必須有 0+ 個字符,盡可能多,后面跟有與第 1 組中相同的值作為整個單詞。(?U)\\b(?:" + String.join("|", results) + ")\\b"
:這個圖案看起來像(?U)\b(?:test|is|Это|тест|также)\b
(?U)
- 嵌入的 UNICODE_CHARACTER_CLASS 標志選項\b
- 字邊界(?:test|is|Это|тест|также)
- 非捕獲交替組\b
- 字邊界
替換是_$0
第二個正則表達式,因為_
附加到整個匹配值$0
。
添加回答
舉報