Регулярное выражение для сопоставления символов:! $% ^ & * () _ + | ~ - = `{} []:"; '<>?,. /

96

Я пытаюсь создать тест Regex в JavaScript, который проверит строку, содержащую любой из этих символов:

!$%^&*()_+|~-=`{}[]:";'<>?,./

Дополнительная информация, если вам интересно :)

Я работаю над довольно классным приложением для смены пароля. Если вам интересно, вот остальная часть кода.

У меня есть таблица, в которой перечислены требования к паролю, и по мере того, как конечные пользователи вводят новый пароль, он проверяет массив регулярных выражений и ставит галочку в соответствующей строке таблицы, если он ... проверяется :) Мне просто нужно добавить этот вместо 4-го элемента в validationмассиве.

var validate = function(password){
    valid = true;

    var validation = [
        RegExp(/[a-z]/).test(password), RegExp(/[A-Z]/).test(password), RegExp(/\d/).test(password), 
        RegExp(/\W|_/).test(password), !RegExp(/\s/).test(password), !RegExp("12345678").test(password), 
        !RegExp($('#txtUsername').val()).test(password), !RegExp("cisco").test(password), 
        !RegExp(/([a-z]|[0-9])\1\1\1/).test(password), (password.length > 7)
    ]

    $.each(validation, function(i){
        if(this)
            $('.form table tr').eq(i+1).attr('class', 'check');
        else{
            $('.form table tr').eq(i+1).attr('class', '');
            valid = false
        }
    });

    return(valid);

}

Да, есть также соответствующая проверка на стороне сервера!

пиксельбобби
источник
9
Довольно забавно, что ответ на ваш вопрос заключается в заголовке, за исключением экранирования специальных символов и включения косых черт.
sciritai 02
1
Почему бы не использовать .addClass("check")и .removeClass("check")? И видение if (someBoolean == true)кода всегда заставляет меня съеживаться. Просто сделай if (someBoolean). Или, еще лучше, просто сделай $(".form table tr").eq(i+1).toggleClass("check", !!this); valid = valid && !!this;.
gilly3 02
+1 @ gill3 thx за обзор кода - действительно отличный отзыв. Я определенно использовал эти короткие методы в прошлом.
pixelbobby 02
@ gilly3, похоже, он отлично работает в FF, но! IE8. люблю это короткометражку. Я пытаюсь понять, что делает IE8 по-другому.
pixelbobby 02

Ответы:

174

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

/[-!$%^&*()_+|~=`{}\[\]:";'<>?,.\/]/

Вам также необходимо экранировать другие метасимволы регулярного выражения.

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

/[$-/:-?{-~!"^_`\[\]]/

Есть три диапазона. '$' в '/', ':' в '?' и '{' в '~'. последняя строка символов не может быть представлена ​​более просто диапазоном:! "^ _` [].

Используйте таблицу ACSII, чтобы найти диапазоны для классов символов.

Джефф Хиллман
источник
Почему не упоминаются кванторы \ Q и \ E для экранирования последовательности символов?
SerG
Прежде чем найти это решение, я пошел по маршруту исключения классов персонажей: сопоставить все, НО альфа, цифры, пробелы и т. Д.
Пит Элвин
1
Общеизвестно, что дефисы должны стоять на первом месте? Я прочитал десятки ответов SO и шпаргалок по регулярным выражениям, это первый, что я слышал об этом. Ваш ответ избавил меня от драмы. Благодарность!
CF_HoneyBadger
2
@SerG \Qи \Eне работают в движке JS RegExp :(/^\Q.\E$/.test('Q+E'); // true
Пол С.
1
@ q4w56 обратная косая черта отсутствует в наборе символов, указанном в исходном вопросе, поэтому несовпадение обратной косой черты является правильным. :)
Джефф Хиллман
7

Самый простой и кратчайший способ добиться этого:

/[^\p{L}\d\s@#]/u

Объяснение

[^...] Соответствует одному символу, отсутствующему в списке ниже

  • \p{L} => соответствует любой букве на любом языке

  • \d => соответствует цифре от нуля до девяти

  • \s => соответствует любому невидимому символу

  • @# => @и #символы

Не забудьте передать uфлаг (unicode).

АмирЗпр
источник
разве вам не понадобится ^, чтобы указать нет?
Уэббер
1
@Webber Нет. Они в столице, и это делает утверждение отрицательным. ^нужен, когда мы употребляем \wи \sмаленькими буквами.
AmirZpr
3
Разве это не интерпретирует его так, что либо снаружи, wлибо снаружи s, и поскольку эти двое на самом деле не пересекаются, он просто пропускает всех персонажей? (Таким образом, ничего не фильтруя.)
Заэль
2
@Zael Вы правы, регулярное выражение, как указано ( /[\W\S]/), пропускает все. Более точное представление о том, что, как я полагаю, имел в виду Амир, было бы [^\w\s]. В первом случае регулярное выражение говорит: «сопоставить все, что не является буквенно-цифровым ИЛИ , не является пробелом», что, как вы упомянули, позволяет выполнить все, поскольку буквенно-цифровые символы не являются пробелами и наоборот. Последний говорит: «Сопоставьте все, что не является буквенно-цифровым и не является пробелом». Конечно, существуют исключения, когда акцентированные символы (например, À) сопоставляются [^\w\s].
Джесси
это не включает _ char
MikeSchem
5

Ответ

/[\W\S_]/

Объяснение

Это создает класс символов, удаляющий символы слова, пробелы и добавляющий обратно символ подчеркивания (поскольку подчеркивание является символом «слова»). Остались только спецсимволы. Заглавные буквы представляют собой отрицание их букв в нижнем регистре.

\Wвыберет все символы, кроме "слова", эквивалентно [^a-zA-Z0-9_]
\Sвыберет все символы, не являющиеся "пробелами", эквивалентно [ \t\n\r\f\v]
_выберет "_", потому что мы инвертируем его при использовании, \Wи необходимо добавить его обратно в

MikeSchem
источник
MikeSchem, ты только что провел меня через машину времени.
pixelbobby
да, я это заметил. был стар, но я чувствовал, что самый простой ответ не был опубликован.
MikeSchem
Чем это отличается от приведенного ниже ответа, в котором отсутствует подчеркивание?
sf8193
-1
// The string must contain at least one special character, escaping reserved RegEx characters to avoid conflict
  const hasSpecial = password => {
    const specialReg = new RegExp(
      '^(?=.*[!@#$%^&*"\\[\\]\\{\\}<>/\\(\\)=\\\\\\-_´+`~\\:;,\\.€\\|])',
    );
    return specialReg.test(password);
  };
Арни Гудьонссон
источник
Не используйте RegExpконструктор, если можно просто использовать литерал регулярного выражения. Гораздо меньше ускользающей работы (большая часть которой в любом случае не нужна), но к тому же она более эффективна.
Берги
Зачем использовать сложный просмотр вперед, если можно просто сопоставить символ напрямую?
Берги
Можете привести пример @Bergi? Я не понимаю, что вы предлагаете.
Arni Gudjonsson
-1

Простой способ добиться этого - отрицательный набор [^ \ w \ s]. По сути, это улавливает:

  • Все, что не является буквенно-цифровым символом (буквы и цифры)
  • Все, что не является пробелом, табуляцией или разрывом строки (все вместе именуемые пробелами)

По какой-то причине [\ W \ S] не работает так же, он не выполняет никакой фильтрации. Комментарий Заэля к одному из ответов дает некоторое объяснение.

Харфель Хакес
источник
Нет, подчеркивание отсутствует, и все символы вне диапазона ascii и большинство управляющих символов в диапазоне ascii будут соответствовать этому классу. /[^\w\s]/.test('é') # true, /[^\w\s]/.test('_') # false.
Казимир и Ипполит
-7

Замените все последние с любого языка на 'A', и, если вы хотите, например, все цифры на 0:

return str.replace(/[^\s!-@[-`{-~]/g, "A").replace(/\d/g, "0");
Ярон Ландау
источник
23
На какой вопрос вы отвечаете?
Тото