bash脚本中的随机字符串生成器不是';t关于给定字符的数量

bash脚本中的随机字符串生成器不是';t关于给定字符的数量,bash,random,Bash,Random,我试图在osx 10.8.5上的bash脚本中构建一个随机字符生成器。目标是为一个脚本生成随机字符串,该脚本为wordpresswp 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} \, \; \. \: \- \_ \# \* \

我试图在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

有没有一种方法可以使字符数与给定的数字保持一致?向拉尔夫致以最诚挚的问候

我发现你的剧本中有两个问题

我很肯定

take=$(($RANDOM % 88));
应该是

take=$(($RANDOM % 87));
否则,看起来您将越过输入流的末尾

另一个问题是这个字符:

Bash将其视为两个字符(宽字符?)。我会把它从你的可能性中删除

当然,这意味着上面的一行是:

take=$(($RANDOM % 86));
LC_CTYPE=C tr -cd 'a-zA-Z0-9,;.:_#*+~!@$%&()=?{[]}|><-' < /dev/urandom | head -c 64
事实上,做这两件事对我很有用

编辑:


@另一个人有更好的答案。添加空格而不是减少模将确保获得每个字符

我发现脚本中存在两个问题

我很肯定

take=$(($RANDOM % 88));
应该是

take=$(($RANDOM % 87));
否则,看起来您将越过输入流的末尾

另一个问题是这个字符:

Bash将其视为两个字符(宽字符?)。我会把它从你的可能性中删除

当然,这意味着上面的一行是:

take=$(($RANDOM % 86));
LC_CTYPE=C tr -cd 'a-zA-Z0-9,;.:_#*+~!@$%&()=?{[]}|><-' < /dev/urandom | head -c 64
事实上,做这两件事对我很有用

编辑:

@另一个人有更好的答案。添加空格而不是减少模将确保获得每个字符

尝试一种更简单的情况:

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 ---^
echo{a..z}{a..z}{0..9}(等)\}\\\\\>\<'''''。。。
#这里---^
请注意,您的方法只是将15位熵添加到salt中,而绝对最小值应为64位。要做到这一点,最简单、更安全的方法是:

take=$(($RANDOM % 86));
LC_CTYPE=C tr -cd 'a-zA-Z0-9,;.:_#*+~!@$%&()=?{[]}|><-' < /dev/urandom | head -c 64
LC#CTYPE=C tr-cd'a-zA-Z0-9;.:#*+~!@$%&()=?{[]}|>试试更简单的例子:

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 ---^
echo{a..z}{a..z}{0..9}(等)\}\\\\\>\<'''''。。。
#这里---^
请注意,您的方法只是将15位熵添加到salt中,而绝对最小值应为64位。要做到这一点,最简单、更安全的方法是:

take=$(($RANDOM % 86));
LC_CTYPE=C tr -cd 'a-zA-Z0-9,;.:_#*+~!@$%&()=?{[]}|><-' < /dev/urandom | head -c 64

LC#CTYPE=C tr-cd'a-zA-Z0-9;.:#*+~!@$%&()=?{[]}|>无意冒犯,您的编码风格是,呃…,不是我见过的最好的
:)

#/bin/bash-e
读取-p“位数:”位数
#TODO:测试数字是否真的是一个数字
字符=({a..z}{a..z}{0..9}\,\;\:\-\\\\\\\\\\\\\\*+\\\~!\§\$\%\&\(\)\=\?\{\[\]\\\\\\\\\\\\\\\+\\\\)
函数rand\u字符串{
本地成本=1美元租金=
当((c-);做
ret+=${chars[$((随机%${#chars[@]}))]}
完成
printf“%s\n”$ret
}
outputsalt=$(随机字符串$位)
回显“$outputsalt”

无意冒犯,您的编码风格是,呃…,不是我见过的最好的
:)

#/bin/bash-e
读取-p“位数:”位数
#TODO:测试数字是否真的是一个数字
字符=({a..z}{a..z}{0..9}\,\;\:\-\\\\\\\\\\\\\\*+\\\~!\§\$\%\&\(\)\=\?\{\[\]\\\\\\\\\\\\\\\+\\\\)
函数rand\u字符串{
本地成本=1美元租金=
当((c-);做
ret+=${chars[$((随机%${#chars[@]}))]}
完成
printf“%s\n”$ret
}
outputsalt=$(随机字符串$位)
回显“$outputsalt”

如果您喜欢一行程序,另一种方法是:

perl -le 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'
perl-le'打印映射{(“a”..z”,“a”..z”,0..9
或者,您可能不希望在结尾处出现新行:

perl -e 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'
perl-e'打印地图{(“a”..z”,“a”..z”,0..9

如果您喜欢一行程序,另一种方法是:

perl -le 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'
perl-le'打印映射{(“a”..z”,“a”..z”,0..9
或者,您可能不希望在结尾处出现新行:

perl -e 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'
perl-e'打印地图{(“a”..z”,“a”..z”,0..9

这不是问题的原因,但你应该在引号中加上
$(rand\u char)
,以防止通配符扩展。也许是个愚蠢的问题。。。但你到底为什么不使用数组呢???这不是问题的原因,但你应该在引号中加上
$(rand_char)
,以防止通配符扩展。也许是个愚蠢的问题。。。但是你到底为什么不使用数组呢???至于
§
(剖面符号):你是对的;具体来说:其Unicode码点为
0xa7
,在7位ASCII范围之外;在UTF8编码中(在OSX上是默认的),您得到2个字节,即
0xc2