• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

PHP wyrażenia regularne, wymagania do hasła, 2 duże, 2 cyfry, kolejność bez znaczenia.

Object Storage Arubacloud
0 głosów
828 wizyt
pytanie zadane 18 kwietnia 2018 w Egzaminy zawodowe przez sebolsita Nowicjusz (120 p.)
Wymóg dla hasła: minimum 2 duże litery, minimum 2 cyfry, tak aby nie musiały być one obok siebie(kolejność nie ma znaczenia).

AAgata01 - prawidłowe

A0gat1A -prawidłowe

0aG1aTa1ag0X- prawidłowe

Agata1 -źle

Ma ktoś pomysł jak napisać takie wyrażenie regularne?
komentarz 18 kwietnia 2018 przez RafalS VIP (122,820 p.)
Wyrażenie regularne do tego będzie chyba trudne, nie mówie, że się nie da, ale mi nic do głowy nie przychodzi. Mam natomiast prostszy sposób na ten problem :P A mianowicie stara dobra pętla for, napisze w łamanym pseudokodzie:
for letter in password
if isLetterUpperCase upperCaseCounter++
if isLetterADigit digitCounter++

Na pewno są gotowe funkcje w php od sprawdzania isUpperCase i isDigit
1
komentarz 18 kwietnia 2018 przez Tomek Sochacki Ekspert (227,510 p.)
Regexp najprostszy może i nie jest, ale do zrobienia :) Wymaga tylko wiedzy czym są tzw. wyprzedzenia pozytywne, a reszta to w sumie standardowe kwantyfikatory i granice ciągu.

1 odpowiedź

+2 głosów
odpowiedź 18 kwietnia 2018 przez Tomek Sochacki Ekspert (227,510 p.)
const reg = /^(?=.*[A-Z].*[A-Z])(?=.*\d.*\d)\w{5,20}$/

reg.test('AAgata01');     //true
reg.test('A0gata1A');     //true
reg.test('0aG1aTa1ag0X'); //true
reg.test('Agata1');       //false

Przykład w JavaScript, bo w PHP już wieki nie pracowałem ale sam regexp będzie taki sam.

Generalnie to składa się on z kilku części:

/^                  //początek analizowanego ciągu znakowego
(?=.*[A-Z].*[A-Z])  //w ciągu muszą być dwie wielkie litery A-Z
(?=.*\d.*\d)        //w ciągu muszą być dwie cyfry 0-9
\w                  //cały ciąg może składać się ze znaków A-Za-z0-9_
{5,20}              //długość ciągu to od 5 do 20 znaków
$/                  //koniec analizowanego ciągu

Dostosuj sobie tylko dwa ostatnie parametry, czyli znaki dopuszczone w haśle oraz jego długość.

Pamiętaj też o obowiązkowym wskazaniu granicy początku i końca ciągu!

Jakby co to pisz, a jak coś nie działa to daj przykładowe dane, na których się wywalają testy.

komentarz 19 kwietnia 2018 przez losowyNICK Nowicjusz (100 p.)
Wydaje mi się że można prościej:

^.+[A-Z0-9]{2,}

 

spośród zbioru...:

AAgata01
AAgata0s
A0gat1A
0aG1aTa1ag0X
Agata1
aGAta123
A0gatAs

 

...wyrażenie spełniają poniższe słowa:

    Line 1: AAgata01
    Line 3: A0gat1A
    Line 4: 0aG1aTa1ag0X
    Line 6: aGAta123
komentarz 19 kwietnia 2018 przez Tomek Sochacki Ekspert (227,510 p.)

Wydaje mi się że można prościej:
^.+[A-Z0-9]{2,}

Można kombinować, aczkolwiek moim zdaniem wersja jaką przedstawiłem daje możliwość stosunkowo łatwego manipulowania kolejnymi kryteriami i niezależnie od nich manipulowania wszystkimi znakami dopuszczonymi w stringu. Ale niezależnie od tego, to Twoja wersja jest błędna i to w kilku miejscach:

const reg = /^.+[A-Z0-9]{2,}/g;

'AAgata01'.match(reg);     //["AAgata01"]
'A0gat1A'.match(reg);      //["A0gat1A"]
'0aG1aTa1ag0X'.match(reg); //["0aG1aTa1ag0X"]
'aGAta123'.match(reg);     //["aGAta123"]

W powyższych przykładach wywołałem metodę match (dodałem też flagę g do regexp) co w JS powoduje zwrócenie dopasowanego fragmentu ciągu znakowego. Widzimy, że pewnie zgodnie z oczekiwaniami zwrócone zostały całe ciągi.

Jest to jednak mylące w tym wypadku i nie do końca działa tak jak oczekujemy. Otóż Twój regexp działa w następujący sposób:

/^.+[A-Z0-9]{2,}/

^.+   //na początku ciągu musi być co najmniej jeden "dowolny" znak
[A-Z0-9]{2,} //a następnie dwa kolejne znaki to litera A-Z lub cyfra

I to jest niezgodne z założeniami problemu, ponieważ jako poprawne uznasz np.:

const reg = /^.+[A-Z0-9]{2,}/;

reg.test('agata55'); //true, brak A-Z!
reg2.test('agaTA'); //true, brak cyfr!

a co więcej, za błędne uznajesz np.:

reg2.test('Ax5xAx5'); //false

a przecież spełniamy warunki:

 2 duże litery, minimum 2 cyfry, tak aby nie musiały być one obok siebie(kolejność nie ma znaczenia).

a tak po za tym, co dopuszczasz w ciągu znakowym praktycznie dowolne znaki, byleby cały ciąg składał się z co najmniej jednego dowolnego znaku i dwóch znaków spełaniających założenia klasy znaków. W żaden sposób nie analizujemy np. długości ciągu itp. - brak granicy "$".

Nie dopuszczasz również dowolnej kolejności znaków, co jest jednym z kryteriów zadania - co widać na powyższych testach.

 

A tak w ogóle, to jeszcze wyjaśnienia wymaga zapis:

[A-Z0-9]{2,}

otóż szuka on ALBO litery A-Z ALBO cyfry i praktycznie dowolna kombinacja tych znaków spełni kryteria, jeśli będą obok siebie. Nie określasz więc, że musi być i litera i cyfra.

A teraz jeszcze wyjaśnienie dlaczego jako false Twój regexp waliduje np. "AGata1_5":

const reg = /^.+[A-Z0-9]{2,}/;

reg.test("AGata1_5"); //false

przecież mamy dwie duże litery (i to ustawione obok siebie) i dwie cyfry. Wiemy już, że ciąg musi mieć A-Z0-9 jako dwa znaki obok siebie, dlatego pewnie rozumiesz, czemu nie dopasuje "1_5", ale pytanie dlaczego nie wyłapał liter "AG" skoro przecież są to A-Z min. 2 razy? Otóż dlatego, że na początku regexp masz ".+", czyli pierwsza litera "A" zostaje dopasowana właśnie przez ten fragment regexp, i dalsza litera "G" nie spełnia wymogu dwóch kolejnych wielkich liter, bo regexp analizuje "Ga".

 

Można by jeszcze dalej iść w analizę tego przypadku, ale nie wiem czy będą osoby zainteresowane taką dyskusją, więc na razie zakończymy na tym :)

Nie odbieraj tego jako jakiś atak na Twoje rozwiązanie - chcę tylko pokazać, jak ważne są w regexp testy pozytywne i negatywne i dbałość o każdy pojedynczy znak, bo czasem można się zdziwić i długo szukać przyczyny problemów :)

Podobne pytania

0 głosów
1 odpowiedź 768 wizyt
pytanie zadane 5 listopada 2018 w PHP przez xxkondzioxx15 Obywatel (1,440 p.)
0 głosów
1 odpowiedź 144 wizyt
pytanie zadane 3 czerwca 2020 w PHP przez Klaudiaaa Początkujący (390 p.)
0 głosów
1 odpowiedź 269 wizyt
pytanie zadane 24 kwietnia 2018 w PHP przez Browarnik123 Użytkownik (830 p.)

92,572 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...