Интервал между последовательными символами в строке с помощью регулярного выражения Java

#java #regex

#java #регулярное выражение

Вопрос:

Я пытаюсь перевести строку и поставить символ подчеркивания перед любым символом верхнего регистра. Самое близкое, что у меня есть, это:

 out=in.replaceAll("([^_])([A-Z])","$1_$2");
  

но с "ABCDEF" он возвращает "A_BC_DE_F" , я думаю, потому что после рассмотрения «AB» он не смотрит на «BC», потому что «B» уже было в предыдущем совпадении. Конечно, я мог бы применить это дважды, но есть ли более элегантное решение?

Существует также:

 out=in.replaceAll("([A-Z])","_$1");
  

но это добавляет начало "_" .

Java 1.8, если это имеет значение

Комментарии:

1. Попробуйте replaceAll("(?<!_)([A-Z])","_$1");

2. Чтобы избежать начала, _ используйте replaceAll("(?<!_|^)([A-Z])","_$1"); или replaceAll("(?<!_)(?<=.)([A-Z])","_$1");

3. Вы можете использовать .replaceAll("(?<=[^_])[A-Z]","_$0"); , просто поместите отрицаемый символьный класс в положительный вид сзади. Нет необходимости заключать весь шаблон использования в захватывающие круглые скобки, $0 обратные ссылки означают полное значение соответствия. Посмотрите эту демонстрацию Java .

Ответ №1:

Вы можете поместить [^_] класс отрицаемых символов в непотребляющий положительный вид сзади

 s = s.replaceAll("(?<=[^_])[A-Z]","_$0");
  

Обратите внимание, что нет необходимости заключать весь шаблон использования в захватывающие круглые скобки, $0 обратная ссылка обозначает полное значение соответствия.

Смотрите эту демонстрацию Java:

 System.out.println(
      "ABCDEF".replaceAll("(?<=[^_])[A-Z]","_$0")
);  // => A_B_C_D_E_F
  

Ответ №2:

Зачем использовать regex??

 String underscoreUppercase(String target){
    StringBuilder b=new StringBuilder();
    boolean first=true;
    for(char c:target.toCharArray()){
        if(Character.isUpperCase(c) amp;amp; !first){//to ommit leading underscore
             b.append('_');
         }
         first=false; 
        b.append(c);
    }

   return b.toString();   
}
  

для ABCDE этого будет A_B_C_D_E

Комментарии:

1. Неожиданно? Чего тогда ожидать? Я пытаюсь перевести строку и поставить символ подчеркивания перед любым символом верхнего регистра

Ответ №3:

Здесь вы можете использовать позитивный прогноз

Регулярное выражение:, ([A-Z])(?=([A-Z])) где (?=([A-Z])) — не требующий использования положительный прогноз

 public static void main(String[] args) {
    String in = "ABCDEF";
    String out = in.replaceAll("([A-Z])(?=([A-Z]))", "$1_");
    System.out.println(out);

}
  

Ответ №4:

В качестве альтернативы вы можете разделить строку на каждый символ верхнего регистра и объединить обратно, используя подчеркивание

 String in  = "ABCDEF";
String out = String.join("_", in.split("(?=\p{Upper})"));
System.out.println(out);
  

Комментарии:

1. Да, тоже хорошее решение. Я предполагал что-то подобное, но не смог заставить это работать.