Regex для замены символов, которые Windows не принимает в имени файла - PullRequest
32 голосов
/ 16 апреля 2009

Я пытаюсь создать регулярное выражение, которое будет определять любой символ, который Windows не принимает как часть имени файла (они одинаковы для других ОС? Я не знаю, если честно).

Эти символы:

 \ / : * ? "  | 

В любом случае, вот что у меня есть: [\\/:*?\"<>|]

Тестер на http://gskinner.com/RegExr/ показывает, что это работает. Для строки Allo*ha загорается символ *, сигнализирующий, что он найден. Однако, если я введу Allo**ha, загорится только первый *. Поэтому я думаю, что мне нужно изменить это регулярное выражение, чтобы найти все появления упомянутых персонажей, но я не уверен.

Видите ли, в Java мне повезло иметь функцию String.replaceAll (регулярное выражение строки, замена строки) . В описании сказано:

Заменяет каждую подстроку этой строки, которая соответствует данному регулярному выражению, с данной заменой.

Другими словами, даже если регулярное выражение только находит первое, а затем прекращает поиск, эта функция все равно найдет их.

Например: String.replaceAll("[\\/:*?\"<>|]","")

Однако я не чувствую, что могу пойти на такой риск. Так кто-нибудь знает, как я могу продлить это?

Ответы [ 11 ]

17 голосов
/ 17 октября 2011

так как ни один ответ не был достаточно хорош, я сделал это сам. надеюсь, это поможет;)

public static boolean validateFileName(String fileName) {
    return fileName.matches("^[^.\\\\/:*?\"<>|]?[^\\\\/:*?\"<>|]*") 
    && getValidFileName(fileName).length()>0;
}

public static String getValidFileName(String fileName) {
    String newFileName = fileName.replace("^\\.+", "").replaceAll("[\\\\/:*?\"<>|]", "");
    if(newFileName.length()==0)
        throw new IllegalStateException(
                "File Name " + fileName + " results in a empty fileName!");
    return newFileName;
}
14 голосов
/ 16 апреля 2009

Правила имен файлов Windows: хитро . Вы только царапаете поверхность.

Например, вот некоторые вещи, которые не являются допустимыми именами файлов, помимо перечисленных вами символов:

                                    (yes, that's an empty string)
.
.a
a.
 a                                  (that's a leading space)
a                                   (or a trailing space)
com
prn.txt
[anything over 240 characters]
[any control characters]
[any non-ASCII chracters that don't fit in the system codepage,
 if the filesystem is FAT32]

Удаление специальных символов в одной подпрограмме регулярного выражения, такой как String.replaceAll (), недостаточно; вы можете легко получить что-то недопустимое, например, пустую строку или завершающий символ «.» или «». Замена что-то вроде «[^ A-Za-z0-9 _.] *» На «_» будет лучшим первым шагом. Но вам все равно потребуется высокоуровневая обработка на любой платформе, которую вы используете.

4 голосов
/ 11 декабря 2014

Я использую чистое и простое регулярное выражение. Я даю символы, которые могут произойти, и через отрицание «^» я изменяю все остальные в качестве знака такового. "_"

String fileName = someString.replaceAll ("[^ a-zA-Z0-9 \\. \\ -]", "_");

Например: Если вы не хотите быть в выражении "." затем удалите "\\."

String fileName = someString.replaceAll ("[^ a-zA-Z0-9 \\ -]", "_");

2 голосов
/ 16 апреля 2009

Для записи, POSIX-совместимые системы (включая UNIX и Linux) поддерживают все символы, кроме нулевого символа ('\0') и прямой слеш ('/') в именах файлов. Специальные символы, такие как пробел и звездочка, должны быть экранированы в командной строке, чтобы они не выполняли свои обычные роли.

1 голос
/ 11 июля 2013

Я извлекаю все символы слова и пробельные символы из исходной строки и также проверяю, нет ли пробельных символов в конце строки. Вот мой фрагмент кода в Java.

temp_string = original.replaceAll("[^\\w|\\s]", "");
final_string = temp_string.replaceAll("\\s$", "");

Я думаю, что помог кому-то.

1 голос
/ 16 апреля 2009

Java имеет функцию replaceAll, но у каждого языка программирования есть способ сделать что-то подобное. Например, Perl использует переключатель g для обозначения глобальной замены. Функция sub в Python позволяет указать количество замен. Если по какой-то причине у вашего языка нет эквивалента, вы всегда можете сделать что-то вроде этого:

while (filename.matches(bad_characters)
  filename.replace(bad_characters, "")
0 голосов
/ 28 января 2018

Требуемое регулярное выражение / синтаксис (JS):

.trim().replace(/[\\/:*?\"<>|]/g,"").substring(0,240);

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

другие полезные функции (JS):

.toUppperCase();
.toLowerCase();
.replace(/  /g,' ');     //normalising multiple spaces to one, add before substring.
.includes("str");        //check if a string segment is included in the filename
.split(".").slice(-1);   //get extension, given the entire filename contains a .
0 голосов
/ 08 ноября 2016

Я сделал один очень простой метод , который работает для меня в большинстве распространенных случаев:

// replace special characters that windows doesn't accept
private String replaceSpecialCharacters(String string) {
    return string.replaceAll("[\\*/\\\\!\\|:?<>]", "_")
            .replaceAll("(%22)", "_");
}

% 22 * ​​1009 * кодируется, если в именах файлов есть qoute ( ").

0 голосов
/ 16 октября 2015

Windows также не принимает «%» в качестве имени файла.

Если вы создаете общее выражение, которое может повлиять на файлы, которые в конечном итоге будут перемещены в другую операционную систему, я предлагаю вам добавить больше символов, которые могут иметь проблемы с ними.

Например, в Linux (многие известные мне дистрибутивы) могут возникнуть проблемы с файлами, содержащими [b] &! ] [/ - () [/ b]. Символы допускаются в именах файлов, но они, возможно, должны быть специально обработаны пользователями, и некоторые программы имеют ошибки, вызванные их существованием.

0 голосов
/ 16 апреля 2009

Вы не можете сделать это с одним регулярным выражением, потому что регулярное выражение всегда соответствует подстроке, если вход. Рассмотрим слово Alo*h*a, там нет подстроки, содержащей все * s, и никаких других символов. Так что, если вы можете использовать функцию replaceAll, просто придерживайтесь ее.

Кстати, набор запрещенных символов отличается в других ОС.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...