Regex для замены символов, которые Windows не принимает в имени файла
Я пытаюсь создать регулярное выражение, которое обнаружит любой символ, который Windows не принимает как часть имени файла (это то же самое для других ОС? Честно говоря, не знаю).
эти символы:
/ : * ? " |
в любом случае, это то, что у меня есть: [/:*?"<>|]
тестер на http://gskinner.com/RegExr/ показывает, что это работает.
Для строки Allo*ha
на *
символ загорается, сигнализируя, что он найден. Должен ли я войти Allo**ha
однако, только первый *
загорается. Поэтому я думаю, что мне нужно изменить это регулярное выражение, чтобы найти все появления упомянутых персонажей, но я не уверен.
видите ли, на Java мне повезло, что у меня есть функция строку.replaceAll (регулярное выражение строки, замена строки). В описании говорится:
заменяет каждую подстроку этой строки, которая соответствует заданному регулярному выражению с учетом замена.
другими словами, даже если регулярное выражение найдет только первое, а затем прекратит поиск, эта функция все равно найдет их все.
например: String.replaceAll("[/:*?"<>|]","")
однако я не чувствую, что могу рисковать. Кто-нибудь знает, как я могу это продлить?
11 ответов
правила имени файла Windows являются хитрый. Ты только царапаешь поверхность.
например, вот некоторые вещи, которые не являются допустимыми именами файлов, в дополнение к перечисленным вами chracters:
(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]
удаление специальных символов в одном подзаголовке regex, например String.replaceAll () недостаточно; вы можете легко получить что-то недопустимое, например пустую строку или трейлинг".’ или ‘ ’. Замена чего-то вроде "[^A-Za-z0-9_.]*" с ‘_’ Было бы лучше первый шаг. Но вам все равно понадобится обработка более высокого уровня на любой платформе, которую вы используете.
поскольку ответа не было достаточно, я сделал это сам. надеюсь, это поможет;)
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;
}
для записи POSIX-совместимые системы (включая UNIX и Linux) поддерживают все символы, кроме нулевого символа (''
) и Слэш ('/'
) в именах файлов. Специальные символы, такие как пробел и звездочка, должны быть экранированы в командной строке, чтобы они не выполняли свои обычные роли.
Я использую чистое и простое регулярное выражение. Я даю символы, которые могут произойти, и через отрицание "^" я изменяю все другое как знак такого. "_"
String fileName = someString.replaceAll ("[^a-zA-Z0-9\\.\\-]", "_");
например: Если вы не хотите быть в выражения "."затем удалите"\\."
String fileName = someString.replaceAll ("[^a-zA-Z0-9\\-]", "_");
Java имеет функцию replaceAll, но каждый язык программирования имеет способ сделать что-то подобное. Perl, например, использует g
переключатель для обозначения глобальной замены. В Python
я извлекаю все символы слова и пробелы из исходной строки, а также удостоверяюсь, что символ пробела отсутствует в конце строки. Вот мой фрагмент кода на Java.
temp_string = original.replaceAll("[^\w|\s]", "");
final_string = temp_string.replaceAll("\s$", "");
думаю, я кому-то помог.
вы можете попробовать разрешить только то, что вы хотите, чтобы пользователь мог ввести, например A-Z, a-z и 0-9.
вы не можете сделать это с одним регулярным выражением, потому что регулярное выражение всегда соответствует подстроке, если вход. Рассмотрим слово Alo*h*a
, нет подстроки, которая содержит все *
s, а не какой-либо другой символ. Поэтому, если вы можете использовать функцию replaceAll, просто придерживайтесь ее.
кстати, набор запрещенных символов отличается в других ОС.
Я сделал один очень простой способ это работает для меня наиболее распространенных случаях:
// replace special characters that windows doesn't accept
private String replaceSpecialCharacters(String string) {
return string.replaceAll("[\*/\\!\|:?<>]", "_")
.replaceAll("(%22)", "_");
}
%22 кодируется, если у вас есть qoute (") в именах файлов.
требуемое регулярное выражение / синтаксис (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 .
Windows также не принимает " % " в качестве имени файла.
Если вы создаете общее выражение, которое может повлиять на файлы, которые в конечном итоге будут перемещены в другую операционную систему, я предлагаю вам поместить больше символов, которые могут иметь проблемы с ними.
например, в Linux (многие дистрибутивы я знаю), некоторые пользователи могут иметь проблемы с файлами, содержащими [b]&! ] [ /- () [/b]. Символы разрешены в именах файлов, но они должны быть специально обработаны пользователи и некоторые программы имеют ошибки, вызванные их существованием.