regexp (Match atleast 1 lower case , 1 uppercase , 1 number & 1 special character

2,482 views
Skip to first unread message

DEXTER

unread,
May 16, 2012, 5:41:07 AM5/16/12
to golang-nuts
Hi
How do i check for the existence of atleast 1 lowercase character, 1
uppercase character, 1 number and 1 special character.

The below code does not match the given word

pword = "upperlower01"
var validId = regexp.MustCompile(`^[a-zA-Z0-9]*$`)
if validId.MatchString(srch) {
fmt.Println("This is a valid word")
}

Dexter

chris dollin

unread,
May 16, 2012, 6:12:24 AM5/16/12
to DEXTER, golang-nuts
That RE matches when there's zero or more of (any lowercase
letter, any uppercase letter, and any digit), completely filling the
string you supply. It's rather a long way from what you want.
REs don't do ANY well.

My intial suggestion would be to use four calls to strings.ContainsAny
and AND the results together.

Chris

--
Chris "allusive" Dollin

chris dollin

unread,
May 16, 2012, 6:13:45 AM5/16/12
to DEXTER, golang-nuts
On 16 May 2012 11:12, chris dollin <ehog....@googlemail.com> wrote:

I said:

> REs don't do ANY well.

(a) ANY should have been AND.

(b) AND over the whole string, rather than AND in sequences.

Chris

--
Chris "typoed to fast" Dollin

roger peppe

unread,
May 16, 2012, 6:19:52 AM5/16/12
to chris dollin, DEXTER, golang-nuts
On 16 May 2012 11:12, chris dollin <ehog....@googlemail.com> wrote:
i'd forgotten about the functions in strings, doh!
the passwordOK function can be simpler.

func passwordOK(p string) bool {
for _, testRune := range mustHave {
if strings.IndexFunc(p, testRune) == -1 {
return false
}
}
return true
}

Kyle Lemons

unread,
May 16, 2012, 11:56:05 AM5/16/12
to DEXTER, golang-nuts
I wouldn't use regex for this.  A very naive (but still unicode-aware) option is:



package main

import (
        "fmt"
        "unicode"
)

func validPassword(s string) error {
next:
        for name, classes := range map[string][]*unicode.RangeTable{
                "upper case": {unicode.Upper, unicode.Title},
                "lower case": {unicode.Lower},
                "numeric": {unicode.Number, unicode.Digit},
                "special": {unicode.Space, unicode.Symbol, unicode.Punct, unicode.Mark},
        } {
                for _, r := range s {
                        if unicode.IsOneOf(classes, r) {
                                continue next
                        }
                }
                return fmt.Errorf("password must have at least one %s character", name)
        }
        return nil
}

func main() {
        for _, s := range []string{
                "bad",
                "testPassword",
                "testPa##word",
                "b3tterPa$$w0rd",
        } {
                fmt.Printf("validPassword(%q) = %v\n", s, validPassword(s))
        }
}

(also here)

roger peppe

unread,
May 16, 2012, 12:38:33 PM5/16/12
to golang-nuts
oops, it seems i didn't Reply-All with my original reply.
this is what i wrote (superseded by later message
using strings.Index).

On 16 May 2012 10:41, DEXTER <djc...@gmail.com> wrote:
it seems to match to me:
http://play.golang.org/p/gtPbui2CDw

but to answer your question, i don't think it's easy to use a single
regexp for this
problem. i'd probably define/use a single function for each character
class and then loop, checking that the string has an instance of each class:

package main

import (
       "fmt"
       "unicode"
)

func main() {
       for _, p := range []string{"", "Hello1", "overTheHills&FarAway999"} {
               fmt.Printf("%q: %v\n", p, passwordOK(p))
       }
}

var mustHave = []func(rune) bool{
       unicode.IsUpper,
       unicode.IsLower,
       unicode.IsPunct,
       unicode.IsDigit,
}

func passwordOK(p string) bool {
       for _, testRune := range mustHave {
               found := false
               for _, r := range p {
                       if testRune(r) {
                               found = true
                       }
               }
               if !found {
                       return false
               }
       }
       return true
}
Reply all
Reply to author
Forward
0 new messages