在Swift中如何检查一个字符串是否至少包含一个大写字母、一个数字或一个特殊字符?

27

我正在尝试创建一个方法,使用正则表达式找出字符串中是否包含数字、大写字母和特殊字符,如下所示:

 func checkTextSufficientComplexity(var text : String) -> Bool{


            let capitalLetterRegEx  = "[A-Z]+"
            var texttest = NSPredicate(format:"SELF MATCHES %@", capitalLetterRegEx)
            var capitalresult = texttest.evaluateWithObject("AniP")
            println("\(capitalresult)")


            let numberRegEx  = "[0-9]+"
            var texttest1 = NSPredicate(format:"SELF MATCHES %@", numberRegEx)
            var numberresult = texttest1.evaluateWithObject(text)
            println("\(numberresult)")


            let specialCharacterRegEx  = "[.*&^%$#@()/]+"
            var texttest2 = NSPredicate(format:"SELF MATCHES %@", numberRegEx)

            var specialresult = texttest2.evaluateWithObject(text)
            println("\(specialresult)")

           return capitalresult && numberresult && specialresult

    }

问题是下面的正则表达式[A-Z]+仅对例如AVATAR返回True,而对于Avatar返回False。我的要求是只要字符串中至少包含一个大写字母,正则表达式就应该返回True。


我没有理解,请您能详细说明一下那个正则表达式吗? - LC 웃
可能是evaluateWithObject函数调用尝试匹配整个字符串,因此,给出这样的字符串:Hello123,以及一个正则表达式:[A-Z]+,Swift会将其映射为类似于^[A-Z]+$的东西。这意味着它将期望整个提供的字符串完全匹配。请尝试进行更改,如果有效,我将发布一篇带有更多信息的答案。我不是Swift开发人员,所以我可能是错的,这就是为什么我把它作为评论发布的原因。 - npinti
谢谢您的解释。但是它没有起作用 :( - LC 웃
@npinti 正则表达式不匹配,返回 false... @rory 我觉得那不是我的情况。 - LC 웃
这对我来说看起来是一个理想的解决方案:https://dev59.com/62cs5IYBdhLWcg3wRB7h - Rory McKinnel
显示剩余3条评论
4个回答

47

只需将你的正则表达式规则[A-Z]+替换为.*[A-Z]+.*(以及其他正则表达式规则)

规则

  

[A-Z]+仅匹配所有字符都为大写字母的字符串

示例:AVATAR、AVA、TAR、AAAAAA
无法工作的示例:AVATAr

  

.*匹配所有字符串(0个或多个字符)

示例:1、2、AVATAR、AVA、TAR、a、b、c

  

.*[A-Z]+.*匹配至少有一个大写字母的所有字符串

示例:Avatar、avataR、aVatar

说明:

I. .*将尝试匹配0个或多个任何字符
II. [A-Z]+将要求至少有一个大写字母(因为+)
III. .*将尝试匹配0个或多个任何字符

  

Avatar [空 | "A" | "vatar"]
  aVatar ["a" | "V" | "atar"]
  aVAtar ["a" | "VA" | "tar"]

有效代码

func checkTextSufficientComplexity(var text : String) -> Bool{


    let capitalLetterRegEx  = ".*[A-Z]+.*"
    var texttest = NSPredicate(format:"SELF MATCHES %@", capitalLetterRegEx)
    var capitalresult = texttest!.evaluateWithObject(text)
    println("\(capitalresult)")


    let numberRegEx  = ".*[0-9]+.*"
    var texttest1 = NSPredicate(format:"SELF MATCHES %@", numberRegEx)
    var numberresult = texttest1!.evaluateWithObject(text)
    println("\(numberresult)")


    let specialCharacterRegEx  = ".*[!&^%$#@()/]+.*"
    var texttest2 = NSPredicate(format:"SELF MATCHES %@", specialCharacterRegEx)

    var specialresult = texttest2!.evaluateWithObject(text)
    println("\(specialresult)")

    return capitalresult || numberresult || specialresult

}

例子:

checkTextSufficientComplexity("Avatar") // true || false || false
checkTextSufficientComplexity("avatar") // false || false || false
checkTextSufficientComplexity("avatar1") // false || true || false
checkTextSufficientComplexity("avatar!") // false || false || true

1
注意:如果您需要应用所有规则,请将“||”替换为“&&”。 - Joshua Arvin Lat
你知道那个不起作用...所有三个结果都是true...尽管我只插入数字...因为 .* 匹配所有字符串。 - LC 웃
原始代码中有一些拼写错误,例如 texttest.evaluateWithObject("AniP") 应该替换为 texttest.evaluateWithObject(text) 以便评估参数。同时,texttest2 也使用了数字正则表达式(应该使用特殊字符正则表达式):) - Joshua Arvin Lat
这就是为什么所有三个结果都会评估为true的原因,因为第一个表达式总是会评估为true,而第二个和第三个表达式正在做同样的事情。 - Joshua Arvin Lat
没问题,@anishparajuli! - Joshua Arvin Lat
添加了一些特殊字符:".*[\".,!&~``^%$#_<>@(+)/-]+.*" - Tung Fam

15

这是Joshua在Swift 3中的简明答案,假设所有验证必须得到满足。

func validate(password: String) -> Bool {
    let capitalLetterRegEx  = ".*[A-Z]+.*"
    let texttest = NSPredicate(format:"SELF MATCHES %@", capitalLetterRegEx)
    guard texttest.evaluate(with: password) else { return false }

    let numberRegEx  = ".*[0-9]+.*"
    let texttest1 = NSPredicate(format:"SELF MATCHES %@", numberRegEx)
    guard texttest1.evaluate(with: password) else { return false }

    let specialCharacterRegEx  = ".*[!&^%$#@()/_*+-]+.*"
    let texttest2 = NSPredicate(format:"SELF MATCHES %@", specialCharacterRegEx)
    guard texttest2.evaluate(with: password) else { return false }

    return true
}

7

另一种替代方案。

您可以使用一个正则表达式完成所有检查。

RegExp: ^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}

您可以按照以下方式使用它:
//Minimum 8 characters at least 1 Uppercase Alphabet, 1 Lowercase Alphabet, 1 Number and 1 Special Character:
let regex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}"
let isMatched = NSPredicate(format:"SELF MATCHES %@", regex).evaluate(with: yourTextField.text)
if(isMatched  == true) {
    // Do your stuff ..
}  else {
    // Show Error Message.
}

更好了...谢谢 - pierre23

5
至少包含1个大写字母、1个小写字母、1个特殊字符、1个数字,总长度为8个字符。

支持https://www.owasp.org/index.php/Password_special_characters中列出的所有特殊字符。

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

extension String {
    func isValidPassword() -> Bool {
        //let passwordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[ !\"\\\\#$%&'()*+,-./:;<=>?@\\[\\]^_`{|}~])[A-Za-z\\d !\"\\\\#$%&'()*+,-./:;<=>?@\\[\\]^_`{|}~]{8,}"
        //safe to escape all regex chars
        let passwordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[ !\"\\\\#$%&'\\(\\)\\*+,\\-\\./:;<=>?@\\[\\]^_`\\{|\\}~])[A-Za-z\\d !\"\\\\#$%&'\\(\\)\\*+,\\-\\./:;<=>?@\\[\\]^_`\\{|\\}~]{8,}"
        return NSPredicate(format: "SELF MATCHES %@", passwordRegex).evaluate(with: self)
    }
}

这个正则表达式在Swift 5中对我来说效果更好。@Patrick R的那个似乎不起作用。啊,神秘的正则表达式又一次让人困惑了。 - Nick N
干得好!<3 - Antonio Labra
你是最棒的。 - Ahmed Abdallah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接