我正在尝试在osx 10.8.5上的bash脚本中构建一个随机字符生成器。目标是为生成wordpress wp-config.php
文件的盐的脚本生成随机字符串。该代码段如下所示:
#!/bin/bash -e
read -p "Number of digits: " digits
function rand_char {
take=$(($RANDOM % 88)); i=0; echo {a..z} {A..Z} {0..9} \, \; \. \: \- \_ \# \* \+ \~ \! \§ \$ \% \& \( \) \= \? \{ \[ \] \} \| \> \< | while read -d\ char;
do
[ "$i" = "$take" ] && echo "$char\c";
((i++));
done
}
function rand_string {
c=$1;
while [ $c -gt 0 ];
do char="${char}"$(rand_char);
let c=$c-1;
done
echo $char
}
outputsalt=`rand_string $digits`
echo $outputsalt
如果我输入64作为生成的字符数不同的位数,则尝试:
HeF6D>z}x[v=s(qRoPmNkLiIfG7E5C3A1yZwWtU§S~Q*O_M:J,b86|4]2{0)X&p (63 chars)
WtUrSpQnOkLiJ,H8F6D4B1yZ)X&V$T!R+P_M:e;c9a7>5}2{u=s(q%o§m~j#hIfG (64 chars)
_g:d,b86|4]w{u=r&p$n!lMjKhIeFcDaB>z0xYt)r&p§m~kLiJgHeFcDA1yZwX (62 chars)
}w{u=s(q%oPmNkKhIfGdEbC3A1xYvWtUrS~Q*O_L.J,H8F6|4]2?Z)X&V$n!l+j_ (64 chars)
l+j_g:e;cDaB>z}x{u=sTqRoPmNkKhIfG7E5C3A1xYvW%U§S~Q*O_L.J,b86|4] (63 chars)
有没有一种方法可以使字符数符合指定的数字?最好的问候拉尔夫
答案 0 :(得分:5)
尝试更简单的案例:
function rand_char {
take=$(($RANDOM % 2)); i=0; echo a b | while read -d\ char;
do
[ "$i" = "$take" ] && echo "$char\c";
((i++));
done
}
它会产生a
和空白,但不会产生b
。
我们可以将问题进一步减少到:
echo a b | while read -d\ char; do echo "$char"; done
仅编写a
而非b
。这是因为您指示read
读取空格,b
之后没有空格,因此失败。这意味着每88个字符中就有一个会掉线,导致你的线条略短。
最简单的解决方法是添加一个伪参数以强制结尾处的空格:
echo {a..z} {A..Z} {0..9} (etc etc) \} \| \> \< '' | while read ...
# Here ---^
请注意,您的方法只会向salt添加15位熵,而绝对最小值应为64.执行此操作的更简单,更安全的方法是:
LC_CTYPE=C tr -cd 'a-zA-Z0-9,;.:_#*+~!@$%&()=?{[]}|><-' < /dev/urandom | head -c 64
(注意:这会用ascii @替换你的unicode段落符号)
答案 1 :(得分:4)
根据你的编码风格,没有冒犯,错误......,而不是我见过的最好的:)
。
#!/bin/bash -e
read -p "Number of digits: " digits
# TODO: test that digits is really a number
chars=( {a..z} {A..Z} {0..9} \, \; \. \: \- \_ \# \* \+ \~ \! \§ \$ \% \& \( \) \= \? \{ \[ \] \} \| \> \< )
function rand_string {
local c=$1 ret=
while((c--)); do
ret+=${chars[$((RANDOM%${#chars[@]}))]}
done
printf '%s\n' "$ret"
}
outputsalt=$(rand_string $digits)
echo "$outputsalt"
答案 2 :(得分:1)
我在你的剧本中看到两个问题。
我很确定
take=$(($RANDOM % 88));
应该是
take=$(($RANDOM % 87));
否则,您似乎已经超过了输入流的末尾。
另一个问题是这个字符:\§
Bash认为这是两个字符(宽字符?)。我会从你的可能性中删除它。
当然,这意味着上述行将是:
take=$(($RANDOM % 86));
事实上,做这两件事对我有用。
编辑:
@其他人有更好的答案。添加空格而不是减少模数将确保您获得每个字符
答案 3 :(得分:0)
如果你喜欢单行,另一种方法是这样做:
perl -le 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'
或者,因为你可能在最后想要一个新行:
perl -e 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'