Java Regex a-z, A-Z, 0-9 и (.)(_)(-)

#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. Идея заключается в том, что он предоставляет интерфейс для функциональности, общей для разных платформ, но реализованной по-разному. Это потому, что каждый делает это по-разному, что это работает так хорошо. Единственная реальная проблема заключается в том, что одна платформа сообщает другой платформе, что нормально, а что нет. И, как я уже сказал, это просто мысль, чтобы дать возможность для других идей.