regex - 检查字符串是否包含 1 个数字、1 个字母且长度在 5-15 个字符之间

标签 regex swift validation passwords predicate

我使用以下扩展来确保字符串至少有 1 个数字、1 个字母且长度在 5-15 个字符之间,我觉得它可以更有效。有什么建议吗?

func checkPassword(密码:字符串) -> Bool{

    if password.characters.count > 15 || password.characters.count < 5 {
        return false
    }


    let capitalLetterRegEx  = ".*[A-Za-z]+.*"
    let texttest = NSPredicate(format:"SELF MATCHES %@", capitalLetterRegEx)
    let capitalresult = texttest.evaluate(with: password)

    let numberRegEx  = ".*[0-9]+.*"
    let texttest1 = NSPredicate(format:"SELF MATCHES %@", numberRegEx)
    let numberresult = texttest1.evaluate(with: password)

    let specialRegEx  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789"
    let texttest2 = NSPredicate(format:"SELF MATCHES %@", specialRegEx)
    let specialresult = !texttest2.evaluate(with: password)




    if !capitalresult || !numberresult || !specialresult  {
        return false
    }

    return true

}

最佳答案

使用正则表达式

正则表达式是一种方法,但如果使用它,我们可以将您的规范合并到单个正则表达式搜索中,并利用以下问答中的正向先行断言技术:

这里,使用正则表达式:

^(?=.*[A-Za-z])(?=.*[0-9])(?!.*[^A-Za-z0-9]).{5,15}$

// where:
// (?=.*[A-Za-z])     Ensures string has at least one letter.
// (?=.*[0-9])        Ensures string has at least one digit.
// (?!.*[^A-Za-z0-9]) Ensures string has no invalid (non-letter/-digit) chars.
// .{5,15}            Ensures length of string is in span 5...15.

其中我还包含一个否定的先行断言 (?!...),以便在给定任何无效字符的情况下使密码无效。

我们可以按如下方式实现正则表达式搜索:

extension String {
    func isValidPassword() -> Bool {
        let regexInclude = try! NSRegularExpression(pattern: "^(?=.*[A-Za-z])(?=.*[0-9])(?!.*[^A-Za-z0-9]).{5,15}$")
        return regexInclude.firstMatch(in: self, options: [], range: NSRange(location: 0, length: characters.count)) != nil
    }
}

let pw1 = "hs1bés2"  // invalid character
let pw2 = "12345678" // no letters
let pw3 = "shrt"     // short
let pw4 = "A12345"   // ok

print(pw1.isValidPassword()) // false
print(pw2.isValidPassword()) // false
print(pw3.isValidPassword()) // false
print(pw4.isValidPassword()) // true

使用Set/CharacterSet

Swift 原生方法是使用显式指定的字符集:

extension String {
    private static var numbersSet = Set("1234567890".characters)
    private static var alphabetSet = Set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters)

    func isValidPassword() -> Bool {
        return 5...15 ~= characters.count &&
            characters.contains(where: String.numbersSet.contains) &&
            characters.contains(where: String.alphabetSet.contains)
    }
}

或者,类似地,在 CharacterSet 上使用 Foundation 方法 rangeOfCharacter(from:):

extension String {
    private static var numbersSet = CharacterSet(charactersIn: "1234567890")
    private static var alphabetSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ")

    func isValidPassword() -> Bool {
        return 5...15 ~= characters.count &&
            rangeOfCharacter(from: String.numbersSet) != nil &&
            rangeOfCharacter(from: String.alphabetSet) != nil
    }
}

如果您还想拒绝包含指定集合中不存在的任何字符的密码,您可以在集合的(倒置)并集上添加搜索操作(可能您还可以允许您希望包含在该联合中的一些特殊字符)。例如,对于 CharacterSet 示例:

extension String {
    private static var numbersSet = CharacterSet(charactersIn: "1234567890")
    private static var alphabetSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ")

    func isValidPassword() -> Bool {
        return 5...15 ~= characters.count &&
            rangeOfCharacter(from: String.numbersSet.union(String.alphabetSet).inverted) == nil &&
            rangeOfCharacter(from: String.numbersSet) != nil &&
            rangeOfCharacter(from: String.alphabetSet) != nil
    }
}

let pw1 = "hs1bés2"  // invalid character
let pw2 = "12345678" // no letter
let pw3 = "shrt"     // too short
let pw4 = "A12345"   // OK

print(pw1.isValidPassword()) // false
print(pw2.isValidPassword()) // false
print(pw3.isValidPassword()) // false
print(pw4.isValidPassword()) // true

使用模式匹配

仅供讨论,另一种方法是使用 native Swift 模式匹配:

extension String {
    private static var numberPattern = Character("0")..."9"
    private static var alphabetPattern = Character("a")..."z"

    func isValidPassword() -> Bool {
        return 5...15 ~= characters.count &&
            characters.contains { String.numberPattern ~= $0 } &&
            lowercased().characters.contains { String.alphabetPattern ~= $0 }
    }
}

let pw1 = "hs1bs2"
let pw2 = "12345678"
let pw3 = "shrt"
let pw4 = "A12345"

print(pw1.isValidPassword()) // true
print(pw2.isValidPassword()) // false
print(pw3.isValidPassword()) // false
print(pw4.isValidPassword()) // true

请注意,此方法将允许带有变音符号(和类似符号)的字母作为最小 1 个字母规范通过,例如:

let diacritic: Character = "é"
print(Character("a")..."z" ~= diacritic) // true

let pw5 = "12345é6"
print(pw5.isValidPassword()) // true

因为这些包含字符范围“a”...“z”;参见例如以下线程中的出色答案:

关于regex - 检查字符串是否包含 1 个数字、1 个字母且长度在 5-15 个字符之间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41383175/

相关文章:

javascript - 正则表达式两个字符串变量

swift - TableView 不从外部数据源调用 cellsForRow

hibernate - 如何使用 Hibernate 验证架构(所有错误)

Android:对话框关闭而不调用关闭

javascript - 可选组在正则表达式中不起作用

java - 用java清理html属性

ios - 双击手势功能仅在第一次点击后触发,每隔一次它需要 2 次点击

swift - 使用GCD在Swift中的另一个函数之后调用函数

zend-framework2 - zf2 formFilter 正则表达式 howto

c# - 正则表达式删除尾随空格和多个空行