Java RegEx - как предотвратить замену строки специальных символов только одним другим символом?

То, что я хочу сделать с регулярным выражением (Regex), в основном является a-single-special">напротив этого запроса.

В настоящее время я использую этот шаблон для создания имен файлов, совместимых с URL:

String new_file_name = old_file_name.replaceAll("[^a-zA-Z0-9._]+", "_"); 

Если есть например например

String old_file_name = "!§$%&{}[]()=´´```_lol_á_^_°.PNG";

тогда новое_имя_файла будет следующим с приведенным выше шаблоном: __lol______.PNG

Однако я хочу, чтобы было по-другому. Этот шаблон регулярного выражения удаляет целые последовательные строки специальных символов всего одним символом подчеркивания, но я хочу, чтобы шаблон заменял КАЖДОЕ ЕДИНСТВЕННОЕ ВСТРЕЧЕНИЕ специального символа его собственным подчеркиванием, которое вместо этого дало бы мне этот результат:

__________________lol______.PNG 

Есть ли способ добиться этого с помощью регулярных выражений?

Редактирование после ответа:
Спасибо, ребята, за ваши замечательные ответы! Мне действительно очень помог! Для полноты картины я хочу предоставить вам мой неуклюжий и неуклюжий фрагмент кода, с помощью которого я добился того же результата, что и указанное вами регулярное выражение:

  for(int i = 0; i < old_file_name.length(); i++)
    {
        // if it is a letter, a number, a underscore or a dot
        if(     (((int)old_file_name.charAt(i) > 47)  &&  ((int)old_file_name.charAt(i) < 58 )) ||
                (((int)old_file_name.charAt(i) > 64)  &&  ((int)old_file_name.charAt(i) < 91 )) ||
                (((int)old_file_name.charAt(i) > 96)  &&  ((int)old_file_name.charAt(i) < 123 )) ||
                ((int)old_file_name.charAt(i) == 95) ||
                ((int)old_file_name.charAt(i) == 46)  )
        {

            // do nothing
        } // end if
        else
        {
            new_file_name = new_file_name.replace(old_file_name.charAt(i), '_');

            // System.out.println("Step " + i + " : " + new_file_name); // for debugging
        } // end if-else
     } // end for 

person Bruder Lustig    schedule 02.06.2017    source источник
comment
newmsg = message.replaceAll(([^a-zA-Z0-9._])+, _);   -  person Neel    schedule 02.06.2017
comment
Вы знаете, что представляет + в регулярном выражении?   -  person Pshemo    schedule 02.06.2017


Ответы (3)


Вы должны удалить + в конце [^a-zA-Z0-9._], чтобы вы могли использовать:

String new_file_name = old_file_name.replaceAll("[^a-zA-Z0-9._]", "_");
//-------------------------------------------------------------^

Вывод

__________________lol______.PNG 

потому что + означает Сопоставить один или несколько раз, но в вашем случае вам нужно заменить их все, поэтому вам не нужен +.

person YCF_L    schedule 02.06.2017

«+» в конце вашего регулярного выражения говорит: «соберите все эти символы подряд и замените их всеми этой второй строкой». Вы хотите удалить "+", и он должен работать нормально. Вы уже используете "String.replaceAll()", который будет повторять замену столько раз, сколько возможно во всей входной строке.

person CWF    schedule 02.06.2017

Вам просто нужно убрать "+". Это решит проблему.

https://regex101.com/r/Lxbc3z/2

person Neel    schedule 02.06.2017