Java 用大写字母替换特定字符前后的字符

Java replace characters with uppercase around (before and after) specific character

我有这样的输入法

word w'ord wo'rd

我需要将单词开头和 ' 字符(可以存在多次)之后的两个字符都转换为大写。

我需要的输出(使用前面的例子)是

word W'Ord Wo'Rd

我尝试了一个简单的模式

s.replaceAll("(\w)(\w*)'(\w)", "");

但我无法将第 1 组和第 3 组转换为大写


编辑: 在发现主要问题中的一个小错误后,我编辑了@Wiktor Stribizew 代码以包含我遗漏的案例。

Matcher m = Pattern.compile("(\w)(\w*)'(\w)").matcher(s);
StringBuffer result = new StringBuffer();
while (m.find()) {
    m.appendReplacement(result, m.group(1).toUpperCase() + m.group(2) + "'" + m.group(3).toUpperCase());
}
m.appendTail(result);
s = result.toString();

您需要在 Java 中使用 Matcher#appendReplacement 才能处理匹配。这是一个例子:

String s = "word w'ord wo'rd";
StringBuffer result = new StringBuffer();
Matcher m = Pattern.compile("\b(\w)(\w*)'(\w(?:'\w)*)").matcher(s);
while (m.find()) {
    m.appendReplacement(result, 
        m.group(1).toUpperCase()+m.group(2) + "'" + m.group(3).toUpperCase());
}
m.appendTail(result);
System.out.println(result.toString());
// => word W'Ord Wo'Rd

Java demo

Java 9+ 等效 (demo):

String s = "wo'rd w'ord wo'r'd";
Matcher m = Pattern.compile("\b(\w)(\w*)'(\w(?:'\w)*)").matcher(s);
System.out.println(
    m.replaceAll(r -> r.group(1).toUpperCase()+r.group(2) + "'" + r.group(3).toUpperCase())
);
//wo'rd w'ord wo'r'd => Wo'Rd W'Ord Wo'R'D
//word w'ord wo'rd => word W'Ord Wo'Rd

模式分解:

  • \b - 前导词边界
  • (\w) - 第 1 组:单个单词 char
  • (\w*) - 第 2 组:零个或多个单词字符
  • ' - 单引号
  • (\w(?:'\w)*) - 第 3 组:
    • \w - 一个字 char
    • (?:'\w)* - 零个或多个序列:
      • ' - 单引号
      • \w - 一个字字符。

现在,如果您想使模式更精确,您可以将应该匹配小写字母的 \w 更改为 \p{Ll} 和应该匹配小写字母的 \w\p{L} 匹配任何字母。该模式看起来像 "(?U)\b(\p{Ll})(\p{L}*)'(\p{Ll}(?:'\p{Ll})*)" - 但是,如果在小写字母之前有大写字母(如 wo'r'D's -> Wo'R'D's). (?U) 是一个 Pattern.UNICODE_CHARACTER_CLASS 内联修饰符,它使 \b 字边界识别 Unicode。

不如上面的 @Wiktor Stribizew post 优雅,但尝试不使用正则表达式:

public class HelloWorld{

 public static void main(String []args){
    String s ="word w'ord wo'r'd";
    System.out.println(upperCase(s,'\''));
 }
 private static int x = 1;
 private static String upperCase(String originalString, char delimeter)
 {
     if(originalString.length()==1)
     {
         return originalString;
     }
     int indexOfDelimeter = originalString.indexOf(delimeter);
     StringBuilder result = new StringBuilder();
     if(indexOfDelimeter<0)
     {
         return originalString;
     }
     String newBaseString = originalString.substring(indexOfDelimeter+2);
     if(indexOfDelimeter==0)
     {
         result.append(delimeter).append(Character.toUpperCase(originalString.charAt(indexOfDelimeter+1))).append(newBaseString);
     }
     else
     {
         result.append(originalString.substring(0,indexOfDelimeter-1)).append(Character.toUpperCase(originalString.charAt(indexOfDelimeter-1))).append(delimeter).append(Character.toUpperCase(originalString.charAt(indexOfDelimeter+1)));
     }
     if(indexOfDelimeter<originalString.length())
     {
        result.append(upperCase( newBaseString,delimeter));
     }
     return result.toString();
 }
}