Bash正则表达式用于强密码

4
我该如何在BASH脚本中使用以下正则表达式?
(?=^.{8,255}$)((?=.*\d)(?!.*\s)(?=.*[A-Z])(?=.*[a-z]))^.*

我需要检查用户输入(密码)是否满足以下条件:
  1. 至少包含一个大写字母。
  2. 至少包含一个数字。
  3. 至少包含一个小写字母。
  4. 密码长度应在8到255个字符之间。
5个回答

3

如果您的 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

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" ]]; thenfi

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

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


echo-weak 应该成为一个新的标签... 与 it's-always-friday-in-iceland 并列。 - beggs
谢谢您的评论,但我需要在bash中完成这个任务,因为我的脚本还要做很多其他的事情。 - Debianuser
如果没有问题,显然您可以从Bash脚本中调用rubyperl,类似于调用grep。或者如果您指的是纯Bash,请使用=〜(假设您可以假定最低使用Bash 3.x),但是您需要修改正则表达式(同样适用于grep)。 - Arkku
如果可能的话,我不想使用Perl,并且我无法在BASH中使用上述正则表达式(顺便说一下,在Java中它是有效的)。 我有BASH 4。 - Debianuser
使用不同的正则表达式。最简单的方法是使用三个不同的表达式:[a-z][A-Z][0-9] - Arkku

1

这些匹配与逻辑AND运算符相关联,这意味着唯一的好匹配是当它们全部匹配时。因此,最简单的方法是将这些条件链接在一起进行匹配,并将先前的结果传输到下一个表达式中。然后,如果任何匹配失败,则整个表达式都会失败:

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

我手动输入了所有字符,而不是使用 "[A-Z]" 和 "[a-z]",因为不同的系统区域设置可能将它们替换为 [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

0

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

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


谢谢您的建议,但我想保持我的脚本简单,并且我不希望它依赖于另一个模块或像 Perl 这样的编程语言。 - Debianuser

0

grep 命令使用 -E 选项时,会使用扩展正则表达式(ERE)
从这个文档中可以看出,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链接


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