bash脚本中的随机字符串生成器不尊重给定字符的数量

rpk*_*rpk 1 random bash

我试图在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
Run Code Online (Sandbox Code Playgroud)

如果我输入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)
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以使字符数符合指定的数字?最好的问候拉尔夫

tha*_*guy 5

尝试一个更简单的案例:

function rand_char {
  take=$(($RANDOM % 2)); i=0; echo a b | while read -d\  char;
  do
    [ "$i" = "$take" ] && echo "$char\c";
    ((i++));
  done
}
Run Code Online (Sandbox Code Playgroud)

它会产生a和空白,但没有b.

我们可以进一步将问题减少到:

echo a b | while read -d\  char; do echo "$char"; done
Run Code Online (Sandbox Code Playgroud)

只写a和不写b.这是因为你指示read读取一个空格,并且在b它失败后没有空格.这意味着每88个字符中就有一个会被丢弃,导致你的线条略短.

最简单的解决方法是添加一个伪参数来强制最后的空格:

echo {a..z} {A..Z} {0..9} (etc etc) \} \| \> \< '' | while read ...
#                                       Here ---^
Run Code Online (Sandbox Code Playgroud)

请注意,您的方法只会向salt添加15位熵,而绝对最小值应为64.执行此操作的更简单,更安全的方法是:

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

(注意:这会用ascii @替换你的unicode段落符号)

  • 基于`tr`的命令是一个很好的选择,但是(至少在OSX上)它会以"非法字节序列"失败,除非你用`LC_CTYPE = C`作为前缀(或者更健壮地说,`LC_ALL = C`) :`LC_ALL = C tr -cd'a-zA-Z0-9 ,;.:_#*+〜!@ $%&()=?{[]} |> < - '</ dev/urandom | 头-c 64` (3认同)