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

97

Próbuję utworzyć test Regex w JavaScript, który przetestuje ciąg zawierający dowolny z następujących znaków:

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

Więcej informacji, jeśli jesteś zainteresowany :)

To całkiem fajna aplikacja do zmiany hasła, nad którą pracuję. Jeśli jesteś zainteresowany, oto reszta kodu.

Mam tabelę, która zawiera listę wymagań dotyczących haseł i gdy użytkownicy końcowi wpisują nowe hasło, przetestuje tablicę Regexes i umieści znacznik wyboru w odpowiednim wierszu tabeli, jeśli ... wyszedł :) Muszę tylko dodać to zamiast czwartej pozycji w validationtablicy.

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);

}

Tak, istnieje również odpowiednia weryfikacja po stronie serwera!

pixelbobby
źródło
9
To dość zabawne, że odpowiedź na twoje pytanie leży w tytule, z wyjątkiem unikania znaków specjalnych i zamykania ukośników.
sciritai
1
Dlaczego nie użyć .addClass("check")i .removeClass("check")? A widzenie if (someBoolean == true)w kodzie zawsze mnie kuli. Po prostu zrób if (someBoolean). Albo, jeszcze lepiej, po prostu zrób $(".form table tr").eq(i+1).toggleClass("check", !!this); valid = valid && !!this;.
gilly3
+1 @ gill3 thx za przegląd kodu - naprawdę świetna opinia. Zdecydowanie korzystałem w przeszłości z tych metod short hand.
pixelbobby
@ gilly3, wygląda na to, że działa świetnie w FF, ale! IE8. uwielbiam tę krótką rękę. Próbuję dowiedzieć się, co robi IE8 inaczej.
pixelbobby

Odpowiedzi:

174

Wyrażenie regularne do tego jest naprawdę proste. Po prostu użyj klasy postaci. Łącznik jest znakiem specjalnym w klasach postaci, więc musi być pierwszy:

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

Musisz także zmienić znaczenie innych metaznaków wyrażeń regularnych.

Edycja: łącznik jest specjalny, ponieważ może być używany do reprezentowania zakresu znaków. Tę samą klasę znaków można uprościć za pomocą zakresów do tego:

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

Istnieją trzy zakresy. „$” na „/”, „:” na „?” i „{” na „~”. ostatni ciąg znaków nie może być reprezentowany prościej za pomocą zakresu:! "^ _` [].

Użyj tabeli ACSII, aby znaleźć zakresy dla klas znaków.

Jeff Hillman
źródło
Dlaczego nie wspomina się o kwantyfikatorach \ Q i \ E do ucieczki sekwencji znaków?
SerG
Przed znalezieniem tego rozwiązania szedłem ścieżką wykluczania klas znaków: dopasuj wszystko ALE alfa, cyfry, spacje itp.
Pete Alvin
1
Czy powszechnie wiadomo, że myślniki muszą być pierwsze? Przeczytałem dziesiątki odpowiedzi SO i ściągów wyrażeń regularnych. To pierwsze, jakie o nich słyszałem. Twoja odpowiedź uratowała mi wiele dramatów. Dzięki!
CF_HoneyBadger
2
@SerG \Qi \Enie działają w silniku JS RegExp :(/^\Q.\E$/.test('Q+E'); // true
Paul S.
1
@ q4w56 odwrotnego ukośnika nie ma w zestawie znaków określonych w oryginalnym pytaniu, więc niepasujący lewy ukośnik jest poprawny. :)
Jeff Hillman
7

Najprostszy i najkrótszy sposób, aby to osiągnąć:

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

Wyjaśnienie

[^...] Dopasuj pojedynczy znak, którego nie ma na poniższej liście

  • \p{L} => pasuje do dowolnego rodzaju liter z dowolnego języka

  • \d => dopasowuje cyfrę od zera do dziewięciu

  • \s => pasuje do dowolnego niewidzialnego znaku

  • @# => @i #znaki

Nie zapomnij przekazać uflagi (unicode).

AmirZpr
źródło
czy nie potrzebujesz znaku ^, aby wskazać, że nie?
Webber
1
@Webber Nie. Są w kapitale, a to sprawia, że ​​oświadczenie jest negatywne. ^jest potrzebny, gdy używamy \wi \smałymi literami.
AmirZpr
3
Czy to nie interpretuje tego tak, że na zewnątrz wlub na zewnątrz s, a ponieważ te dwie tak naprawdę nie przecinają się, po prostu przepuszczają wszystkie postacie? (W ten sposób niczego nie filtruje)
Zael
2
@Zael Masz rację, wyrażenie regularne, jak stwierdzono ( /[\W\S]/), przepuszcza wszystko. Bardziej dokładne przedstawienie tego, do czego według mnie dążył Amir [^\w\s]. W pierwszym przypadku wyrażenie regularne mówi „dopasuj wszystko, co nie jest alfanumeryczne LUB co nie jest białą spacją”, co, jak wspomniałeś, pozwala przejść przez wszystko, ponieważ znaki alfanumeryczne nie są białymi spacjami i odwrotnie. Ten ostatni mówi „dopasuj wszystko, co nie jest alfanumeryczne ORAZ nie jest białymi znakami”. Oczywiście obowiązują wyjątki, jeśli znaki akcentowane (jak À) są dopasowywane przez [^\w\s].
Jesse
nie obejmuje to _ char
MikeSchem
5

Odpowiedź

/[\W\S_]/

Wyjaśnienie

Tworzy to klasę znaków, usuwając znaki słowne, znaki spacji i dodając z powrotem znak podkreślenia (ponieważ podkreślenie jest znakiem „słowa”). Pozostały tylko znaki specjalne. Wielkie litery reprezentują negację ich małych odpowiedników.

\Wwybierze wszystkie znaki inne niż "słowo" równoważne z [^a-zA-Z0-9_]
\Swybierze wszystkie znaki inne niż "białe znaki", które są równoważne [ \t\n\r\f\v]
_wybierze "_" ponieważ negujemy to gdy używamy \Wi musimy go dodać ponownie

MikeSchem
źródło
MikeSchem, właśnie przeprowadziłeś mnie przez wehikuł czasu.
pixelbobby
tak, zauważyłem to. był stary, ale czułem, że najprostsza odpowiedź nie została opublikowana.
MikeSchem
czym różni się to od odpowiedzi poniżej, która nie udaje się na podkreśleniu?
sf8193
0

Prostym sposobem osiągnięcia tego jest zbiór ujemny [^ \ w \ s]. To zasadniczo łapie:

  • Wszystko, co nie jest znakiem alfanumerycznym (litery i cyfry)
  • Wszystko, co nie jest spacją, tabulatorem ani podziałem wiersza (łącznie nazywane spacjami)

Z jakiegoś powodu [\ W \ S] nie działa w ten sam sposób, nie filtruje. Komentarz Zaela do jednej z odpowiedzi dostarcza pewnego wyjaśnienia.

Harfel Jaquez
źródło
Nie, brakuje podkreślenia i wszystkie znaki spoza zakresu ascii i większość znaków kontrolnych w zakresie ascii pasowałyby do tej klasy. /[^\w\s]/.test('é') # true, /[^\w\s]/.test('_') # false.
Casimir et Hippolyte
-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);
  };
Arni Gudjonsson
źródło
Nie używaj RegExpkonstruktora, gdy możesz po prostu użyć literału regex. Dużo mniej pracy uciekającej (z których większość i tak jest niepotrzebna), a także bardziej wydajna.
Bergi
Po co używać skomplikowanego lookahead, skoro można bezpośrednio dopasować postać?
Bergi
Czy możesz podać przykład @Bergi? Nie rozumiem, co sugerujesz.
Arni Gudjonsson
-7

Zastąp wszystkie ostatnie litery z dowolnego języka w „A”, a jeśli chcesz na przykład wszystkie cyfry na 0:

return str.replace(/[^\s!-@[-`{-~]/g, "A").replace(/\d/g, "0");
Yaron Landau
źródło
23
Na jakie pytanie odpowiadasz?
Toto