我有一个命令可以生成带有多个特殊字符的密码。我怎样才能让它只生成1个特殊字符?
# Generate a random password
# $1 = number of characters; defaults to 32
# $2 = include special characters; 1 = yes, 0 = no; defaults to 1
function randpass() {
[ "$2" == "0" ] && CHAR="[:alnum:]" || CHAR="[:graph:]"
cat /dev/urandom | tr -cd "$CHAR" | head -c ${1:-32}
echo
}
答案1
这里有几种方法:
1. 不断迭代,直到获得您“喜欢”的密码
while true
do
word=$(tr -cd "[:graph:]" < /dev/urandom | head -c ${1:-32})
if [[ "$word" =~ [[:punct:]].*[[:punct:]] ]]
then
echo "$word has multiple special characters - reject."
continue
fi
if [[ "$word" =~ [[:punct:]] ]]
then
echo "$word has one special character - accept."
break
fi
echo "$word has no special characters - reject."
continue
done
警告:对于大量字符(例如,> 16),这可能需要很长时间。
2. 读到一个标点符号后停止
n=${1:-32}
if [ "$2" == "0" ]
then
CHAR="[:alnum:]"
else
CHAR="[:graph:]"
fi
word=
for ((i=0; i<n; i++))
do
thischar=$(tr -cd "$CHAR" < /dev/urandom | head -c 1)
if ! [[ "$thischar" =~ [[:alnum:]] ]]
# Probably equivalent to if [[ "$thischar" =~ [[:punct:]] ]]
then
# Got one special character – don’t allow any more.
echo "$thischar is a special character."
CHAR="[:alnum:]"
fi
word="$word$thischar"
done
echo "$word"
请注意,这会获取前三个中的特殊字符(例如,ab!defghijklmnopqrstuvwxyz123456
)非常 经常。此外,理论上可以使用这种方法获得没有特殊字符的密码。
答案2
我想我会[:alnum:]
先生成 32 个字符,然后选择性地插入一个特殊字符:
function randpass() {
passwd=$( < /dev/urandom tr -cd "[:alnum:]" | head -c $1)
if [ "$2" == "0" ]; then
echo "$passwd"
else
spchar=$( < /dev/urandom tr -cd "[:punct:]" | head -c 1)
pos=$((RANDOM%$1))
echo "${passwd:0:pos}${spchar}${passwd:pos+1:$1}"
fi
}
我假设包含[:punct:]
您认为“特殊”的所有字符。
语法$(( ))
是shell算术扩展它生成一个 0 到 31 之间的随机数(或任何数字$1
)。
语法${var:offset:length}
是shell参数扩展从字符串返回子字符串。
答案3
只需将head
命令更改为-c 1
:
# Generate a random password
# $1 = number of characters; defaults to 32
# $2 = include special characters; 1 = yes, 0 = no; defaults to 1
function randpass() {
[ "$2" == "0" ] && CHAR="[:alnum:]" || CHAR="[:graph:]"
cat /dev/urandom | tr -cd "$CHAR" | head -c 1
echo
}