【问题标题】:Bash regex for strong password用于强密码的 Bash 正则表达式
【发布时间】:2011-05-11 22:30:18
【问题描述】:

如何在 BASH 脚本中使用以下正则表达式?

(?=^.{8,255}$)((?=.*\d)(?!.*\s)(?=.*[A-Z])(?=.*[a-z]))^.*

我需要检查以下用户输入(密码):

  1. 至少一个大写字母。
  2. 至少一个数字。
  3. 至少一个小写字母。
  4. 密码长度应介于 8 到 255 个字符之间。

【问题讨论】:

    标签: regex bash input passwords


    【解决方案1】:

    我不认为您的正则表达式是检查列表中内容的最佳(或正确?)方法(提示:我会独立于其他条件检查长度),但要回答关于在Bash中使用的问题:使用grep -Eq的返回值,例如:

    if echo "$candidate_password" | grep -Eq "$strong_pw_regex"; then
        echo strong
    else
        echo weak
    fi
    

    或者在 Bash 3 及更高版本中,您可以使用 =~ 运算符:

    if [[ "$candidate_password" =~ "$strong_pw_regex" ]]; then
        …
    fi
    

    grep -E 或 Bash 的正则表达式语法不一定支持您在示例中使用的所有内容,但可以检查您的要求。但是如果你想要更高级的正则表达式,你可能需要用 Ruby 或 Perl 之类的东西来代替 Bash。

    至于修改您的正则表达式,请使用 Bash 检查长度(${#candidate_password} 会为您提供变量 candidate_password 中字符串的长度),然后使用没有前瞻的简单语法。为简单起见,您甚至可以使用单独的正则表达式检查所有三个条件。

    【讨论】:

    • echo-weak 应该是一个新标签...去it's-always-friday-in-iceland旁边
    • 感谢您的评论,但我需要在 bash 中完成此操作,因为我有一个可以执行许多其他操作的脚本。
    • 显然你可以从你的 Bash 脚本中调用rubyperl,如果这不是问题的话,类似于调用grep。或者,如果您的意思是纯 Bash,请使用 =~(假设您可以假设 Bash 3.x 最低),但您需要修改您的正则表达式(grep 也是如此)。
    • 如果可能,我不想使用 Perl,而且我无法在 BASH 中使用上述正则表达式(在 Java 中适用)。我有 BASH 4。
    • 使用不同的正则表达式。最简单的方法是使用三个不同的方法:[a-z][A-Z][0-9]
    【解决方案2】:

    grep-E 选项使用扩展正则表达式 (ERE)
    从此documentation ERE 不支持前瞻。

    因此,您可以将 Perl 用作:

    perl -ne 'exit 1 if(/(?=^.{8,255}$)((?=.*\\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*/);exit 0;'
    

    Ideone Link

    【讨论】:

      【解决方案3】:

      我知道您正在寻找正则表达式,但您是否考虑过通过 PAM 模块来做?

      可能还有其他有趣的模块。

      【讨论】:

      • 感谢您的建议,但我想让我的脚本保持简单,并且我不希望它依赖于另一个模块或像 Perl 这样的编程语言。
      【解决方案4】:

      这些匹配是用逻辑 AND 运算符连接的,这意味着唯一好的匹配是当它们都匹配时。 因此,最简单的方法是匹配那些链接的条件,将先前的结果通过管道传递到下一个表达式中。然后,如果任何匹配失败,则整个表达式失败:

      $echo "tEsTstr1ng" | egrep "^.{8,255}"| egrep "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]"| egrep "[abcdefghijklmnopqrstuvwxyz"] | egrep "[0-9]"
      

      我手动输入了所有字符而不是“[AZ]”和“[az]”,因为不同的系统语言环境可能会将它们替换为 [aAbBcC...,这是一个匹配中的两个条件,我们需要检查 两个条件。

      作为shell脚本:

      #!/bin/sh
      a="tEsTstr1ng"
      b=`echo $a | egrep "^.{8,255}" | \
                   egrep "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]" | \
                   egrep "[abcdefghijklmnopqrstuvwxyz"] | \
                   egrep "[0-9]"`
      # now featuring W in the alphabet string
      #if the result string is empty, one of the conditions has failed
      if [ -z $b ]
        then
          echo "Conditions do not match"
        else
          echo "Conditions match"
      fi
      

      【讨论】:

        【解决方案5】:

        如果您的 grep 版本具有 -P 选项,则它支持 PCRE(Perl 兼容正则表达式。

        grep -P '(?=^.{8,255}$)(?=^[^\s]*$)(?=.*\d)(?=.*[A-Z])(?=.*[a-z])'
        

        我不得不更改您的表达式以拒绝空格,因为它总是失败。额外的一组括号似乎没有必要。我在最后省略了^.*,因为它总是匹配的,你真的只需要这样的布尔结果:

        while ! echo "$password" | grep -P ...
        do
            read -r -s -p "Please enter a password: " password
        done
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-06-16
          • 2018-08-17
          • 2022-12-03
          • 1970-01-01
          • 1970-01-01
          • 2014-04-09
          相关资源
          最近更新 更多