【问题标题】:Java replace characters with uppercase around (before and after) specific characterJava在特定字符周围(之前和之后)用大写替换字符
【发布时间】:2017-04-18 08:21:15
【问题描述】:

我有这种输入法

word w'ord wo'rd

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

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

word W'Ord Wo'Rd

我尝试了一个简单的模式

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

但我无法将组 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 regex uppercase apostrophe


    【解决方案1】:

    您需要在 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 - 一个字字符
      • (?:'\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。

    【讨论】:

    • 这确实有效。运行此代码并查看我需要转换的所有行的输出,我在主要问题中发现了一个小错误。我现在调整了主要问题,以包括我错过的案例
    • 字符串失败:String s = "word w'ord wo'r'd";
    • @DevilingMaster:同样的方法在这里是有效的:将你需要的东西分成组,然后在while块内根据需要操作每个组。
    • @Optional:没问题,使用"\\b(\\w)(\\w*)'(\\w(?:'\\w)*)"正则表达式。
    • 是的,@WiktorStribiżew 是的,明白了
    【解决方案2】:

    不像上面的@Wiktor Stribizew 帖子那样优雅,而是尝试不使用正则表达式:

    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();
     }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 2020-08-26
      相关资源
      最近更新 更多