[VBA] Regex

0

Cześć,

Czy jest możliwe użycie funkcji regex.pattern w jednej linii tak aby spełnić co najmniej 3 z 4 warunków?
TRUE jest tylko wtedy kiedy 3 lub 4 warunki są spełnion z poniższych.

Tekst musi mieć:

Have lower characters
Have upper characters
Have a digit
Have a special character (Regex match [\W_])

moj kod na to wygląda tak:

Sub test()

Dim Text As String
Dim regex As Object
Dim counter As Byte
Dim Bool As Boolean

Text = "abc@123"

Set regex = CreateObject("VBScript.RegExp")

With regex
    
'upper letters
    .Pattern = "[A-Z]+"
    If .test(Text) = True Then
        counter = counter + 1
    End If
    
'lower letters
    .Pattern = "[a-z]+"
    If .test(Text) = True Then
        counter = counter + 1
    End If
    
'digits
    .Pattern = "[0-9]+"
    If .test(Text) = True Then
        counter = counter + 1
    End If
    
'special character
    .Pattern = "[\W]+"
    If .test(Text) = True Then
        counter = counter + 1
    End If
    
If counter >= 3 Then Bool = True
    
End With

Jak widać biorę każdy pattern oddzielnie i liczę warunki.
Regex ma mozliwosc grupowania warunkow ale nie umiem tego wprowadzić.

Proszę o pomoc,
Jacek

1

Można by spróbować z lookahead, lecz wydaje mi się, że nie jest to gra warta świeczki - aktualne podejście jest znacznie czytelniejsze.

1

Przyznam, że podpatrzyłem rozwiązanie z forum. Dodatkową podpowiedź do rozwiązania napisał @Patryk27, żeby wykorzystać lookahead.

^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[\W_]).{4,24}$

W ciągu musi wystąpić przynajmniej jedna wielka litera, jedna mała litera, jedna cyfra oraz znak, który nie jest ani wielką literą, ani małą literą, ani cyfrą. Całość musi się zmieścić (zamknąć) w znakach od 4 do 24.

Jeśli chcesz, aby w ciągu wystąpić mogły np. dwie litery duże, to możesz napisać tak, ale może jest jeszcze inny sposób (?=.*[A-Z].*[A-Z]).{2,24}. I po tym zabiegu, w tekście muszą wystąpić conajmniej dwie wielkie litery, a cały tekst musi być przynajmniej zmieszczony od 2 znaków do 24.

Zamiast pisać .{4,24} można napisać .{1.24}, ale pierwsza wersja oznacza, żeby zaczął liczyć od czwartego znaku, ponieważ po co ma liczyć od pierwszego skoro w tekście muszą wystąpić przynajmniej cztery znaki, ponieważ tak jest napisane we wzorcu, żeby przynajmniej jeden znak z każdej grupy wystąpił, a tych grup jest cztery. Jest takie coś jak [u]defensive programming[/u], ale w tym przypadku to nie ma chyba zastosowania, choć mogę się mylić.

Staraj się nie nadawać takich nazw np. zmiennym jak Dim Text As String, ponieważ ta nazwa jest chyba zajęta przez chyba obiekt we wbudowanej konstrukcji języka. Czyli może wystąpić konflikt nazw.

https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/functions/string-functions

0

Cześc,

dziękuje bardzo.

Mam kilka pytań:
^ - co to oznacza?

I przedstawiłeś rozwiązanie, które musi spełnić 4 warunki z 4 a mi jest potrzebne jesli spelnione sa 3 warunki lub 4 = TRUE.

Dzięki jeszcze raz,
Jacek

0

Zostaw to w obecnej formie tylko wrzuć całość w oddzielną funkcję, która zwróci Ci true lub false. Możesz taką funkcję wywołać wiele razy a dodatkowo zachowasz czytelność kodu. W jednej linii będzie to nieczytelne i niezrozumiałe na pierwszy rzut oka.

0

Cześć Ales,

dzięki :)

1

[vba]

Sub dfg43()

    Dim t1 As String
    Dim r1 As Object
    
    t1 = "uuA88"
    
    Set r1 = CreateObject("VBSCript.RegExp")
    
    With r1
    
        .Pattern = "^((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[\W_]))|((?=.*[a-z])(?=.*[A-Z])(?=.*[\W_])|(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])|(?=.*[a-z])(?=.*[\W_])(?=.*[0-9])|(?=.*[A-Z])(?=.*[\W_])(?=.*[0-9])).*$"

        If .test(t1) Then
            MsgBox ("Found")
        End If
    
    End With

End Sub

Jak będziesz wiedział jak, to uprość ten regex.

Znaki "^" na początku i "$" na końcu oznaczją, żeby wziąć wszystko od samego początku do samego końca dany łańcuch znaków.
Wypróbuj np. taki regex ^.*?abc.*?$. Dla takich danych:

sfdjklfsabc
sdfsdfsabcdsfdsf

Dopasuje wszystko, ale już dla takiego regex .*?abc.*? bez "^" i "$" już wszystkiego nie dopasuje, tylko to:

sfdjklfsabc
sdfsdfsabc

Poczytaj trochę o różnicach w implementacjach regex i o samych regex.

1 użytkowników online, w tym zalogowanych: 0, gości: 1