#java #regex
#java #Регулярное выражение
Вопрос:
Написание простого регулярного выражения, но я никогда не был очень хорош в этом.
Что я пытаюсь сделать, так это проверить строку (имя файла), чтобы убедиться, что она содержит только a-z, A-Z, 0-9 или специальные символы подчеркивания (_), точку (.) или тире (-).
Вот что у меня есть
if(filename.length() < 1 || !filename.matches("^[a-zA-Z0-9[.][_][-]] "))
return false;
else
return true;
Похоже, это работает, но для меня выглядит не очень элегантно. Есть ли лучший / более читаемый способ написать это?
Заранее спасибо! Просто пытаюсь научиться лучше писать эти ошибки.
-Будет
Комментарии:
1. Другие хорошо ответили на вопрос о регулярных выражениях, но мне любопытно, почему вы проверяете, что длина строки больше 1. Если строка «», она не может соответствовать
"^. "
2. Хороший момент. Это осталось от предыдущей реализации. Спасибо!
Ответ №1:
Вам не нужно использовать []
внутри символьного класса.
Итак, вы можете написать:
^[-a-zA-Z0-9._]
Кроме того, вы можете использовать \w
вместо a-zA-Z0-9_
.
Таким образом, регулярное выражение будет:
^[-\w.]
Кроме того, это регулярное выражение будет соответствовать строке, например StackOverflow 22.10$$2011
, путем потребления StackOverflow 22.10
. Если вам нужно, чтобы ваша строка полностью состояла из этих символов, вы должны завершить шаблон $
— конец строки:
^[-\w.] $
Комментарии:
1. Фактически, в большинстве вариантов регулярных выражений эти дополнительные квадратные скобки будут рассматриваться как синтаксическая ошибка.
2. Спасибо! Это выглядит намного лучше
3. Использование \w позволит использовать любой символ UTF-8, а не только a-z и A-Z. Также имейте в виду, что . соответствует любому символу и должен быть экранирован, если вы имеете в виду буквальное ‘.’
4. @MarkRotteveel
.
внутри символьного класса означает буквальный.
, и его не нужно экранировать как внешний символьный класс.5. @MarkRotteveel Что касается
\w
. Я привык к движку регулярных выражений Python. В Python\w
означает строку, подобную человекуw
(мы просто экранируемдругим
, иначе
w
это означало бы только один специальный символ. Обычно мы используемr
перед строкой для обозначенияraw
строки, так что экранирование не требуетсяr'raw sring w*'
.
Ответ №2:
try {
boolean foundMatch = subjectString.matches("^[\w.-] $");
} catch (PatternSyntaxException ex) {
// Syntax error in the regular expression
}
Попробуйте это.
По сути, w — это сокращение для [a-zA-Z_0-9], и я просто добавляю два других символа, которые вы хотите.
Комментарии:
1. Я не знаю движок Java RE engine, но обычно вам нужно привязать к началу строки, иначе будет принято «@ # $% @# $% foo».
2. @OscarKorz уже добавил якоря, прежде чем я увидел комментарий m8 🙂
3.
matches()
Метод Java автоматически закрепляет совпадение на обоих концах, но использование явных якорей не повредит, и я думаю, что это хорошая политика для этого. Однако я не вижу смысла в этом прогнозе (т. Е.(?=[\w.-] $)
). Кроме того, имейте в виду, что исключение PatternSyntaxException — это исключение RuntimeException; вы не обязаны его перехватывать.4. @AlanMoore Lookahed, как написано, просто проверяет, равна ли длина хотя бы единице, что также проверяется OP. Просто хотел показать, что это также возможно с помощью регулярных выражений.
5. Но для вашего regex (
^[\w.-] $
) уже требуется хотя бы один символ. Предварительный просмотр полностью избыточен.
Ответ №3:
Вот метод, который является более дорогостоящим (потому что он фактически касается диска), но будет кроссплатформенным.
По сути, он создает файл с заданным именем и удаляет его, если он ранее не существовал. Если вы попытались создать файл с недопустимым именем, он выдает ошибку. Поэтому независимо от того, в какой системе вы работаете, он сообщит вам, было ли имя файла правильным.
Теперь это нарушает общее правило (использование исключений для определения потока программы) и имеет недостаток в том, что он отправляется на диск. Но это другой подход и может дать вам идеи, которые вы можете использовать.
public boolean isValidFileName(final String fileName) {
final File file = new File(fileName);
final boolean isValid = true;
try {
if (file.createNewFile()) {
file.delete();
}
} catch (IOException e) {
isValid = false;
}
return isValid;
}
Комментарии:
1. Это потенциально вернет разные результаты на разных платформах. Это противоположно тому, что обычно подразумевается под кроссплатформенностью, как я понимаю.
2. Идея заключается в том, что он предоставляет интерфейс для функциональности, общей для разных платформ, но реализованной по-разному. Это потому, что каждый делает это по-разному, что это работает так хорошо. Единственная реальная проблема заключается в том, что одна платформа сообщает другой платформе, что нормально, а что нет. И, как я уже сказал, это просто мысль, чтобы дать возможность для других идей.