【问题标题】:Using "$RANDOM" to generate a random string in Bash使用 "$RANDOM" 在 Bash 中生成随机字符串
【发布时间】:2015-09-09 16:11:01
【问题描述】:

我正在尝试使用 Bash 变量 $RANDOM 创建一个随机字符串,该字符串由来自包含整数和字母数字的变量的 8 个字符组成,例如 var="abcd1234ABCD"

我该怎么做?

【问题讨论】:

    标签: linux bash random


    【解决方案1】:

    使用参数扩展。 ${#chars} 是可能的字符数,% 是模运算符。 ${chars:offset:length} 选择位置 offset 的字符,即在我们的例子中为 0 - length($chars)。

    chars=abcd1234ABCD
    for i in {1..8} ; do
        echo -n "${chars:RANDOM%${#chars}:1}"
    done
    echo
    

    【讨论】:

    • 谢谢,但是我不明白模块 % 的使用,你或有人能解释一下为什么吗?
    • @Dimareal:$RANDOM 可能太大。通过使用模,结果不能大于 $chars 的长度,即你可以用它来索引一个随机字符。
    • 是否有适用于“ash”和“sh”且不仅适用于 bash 的版本?我正在研究运行 OpenWrt 的嵌入式系统,并且由于空间限制,bash 没有空间。我收到此错误:# /tmp/rnd.sh /tmp/rnd.sh: 第 5 行:语法错误:替换错误
    • 如果chars 包含转义字符,这可以启动bash 命令l。试试chars='<=>| -,;:!/."()[]{}*\&#%+012345689abcdefghiklmnopqrstuvwxyz'
    • @MrMartin:不,它不运行任何命令,它只是扩展了一个 glob。通过双引号修复。
    【解决方案2】:

    对于那些在 bash 中寻找随机字母数字字符串的人:

    LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 64

    与有据可查的函数相同:

    function rand-str {
        # Return random alpha-numeric string of given LENGTH
        #
        # Usage: VALUE=$(rand-str $LENGTH)
        #    or: VALUE=$(rand-str)
    
        local DEFAULT_LENGTH=64
        local LENGTH=${1:-$DEFAULT_LENGTH}
    
        LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c $LENGTH
        # LC_ALL=C: required for Mac OS X - https://unix.stackexchange.com/a/363194/403075
        # -dc: delete complementary set == delete all except given set
    }
    

    【讨论】:

    • tr:非法字节序列
    • @Sukima 请尝试在命令前添加 LC_ALL=C 并让我知道它是否有效
    【解决方案3】:

    另一种生成32字节(例如)十六进制字符串的方法:

    xxd -l 32 -c 32 -p < /dev/random
    

    如果您想要大写字符,请添加 -u

    【讨论】:

      【解决方案4】:

      选项 1 - 没有特定的长度,不需要 openssl,只有字母和数字,比 选项 2 慢

      sed "s/[^a-zA-Z0-9]//g" <<< $(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%*()-+' | fold -w 32 | head -n 1)
      

      演示:x=100; while [ $x -gt 0 ]; do sed "s/[^a-zA-Z0-9]//g" &lt;&lt;&lt; $(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%*()-+' | fold -w 32 | head -n 1) &lt;&lt;&lt; $(openssl rand -base64 17); x=$(($x-1)); done

      例子:

      j0PYAlRI1r8zIoOSyBhh9MTtrhcI6d
      nrCaiO35BWWQvHE66PjMLGVJPkZ6GBK
      0WUHqiXgxLq0V0mBw2d7uafhZt2s
      c1KyNeznHltcRrudYpLtDZIc1
      edIUBRfttFHVM6Ru7h73StzDnG
      

      选项 2 - 没有特定长度,openssl 需要,只有字母和数字,比选项 1

      openssl rand -base64 12 # only returns
      
      rand=$(openssl rand -base64 12) # only saves to var
      
      sed "s/[^a-zA-Z0-9]//g" <<< $(openssl rand -base64 17) # leave only letters and numbers
      # The last command can go to a var too.
      

      演示:x=100; while [ $x -gt 0 ]; do sed "s/[^a-zA-Z0-9]//g" &lt;&lt;&lt; $(openssl rand -base64 17); x=$(($x-1)); done

      例子:

      9FbVwZZRQeZSARCH
      9f8869EVaUS2jA7Y
      V5TJ541atfSQQwNI
      V7tgXaVzmBhciXxS
      

      【讨论】:

        【解决方案5】:

        没有使用$RANDOM,但值得一提。

        使用 shuf 作为熵源(又名随机性)(反过来,可以使用 /dev/random 作为熵源。如 `shuf -i1-10 --random-source=/dev/urandom)看起来像使用更少资源的解决方案:

        $ shuf -er -n8  {A..Z} {a..z} {0..9} | paste -sd ""
        tf8ZDZ4U
        

        【讨论】:

          【解决方案6】:
          head -1 <(fold -w 20  <(tr -dc 'a-zA-Z0-9' < /dev/urandom))
          

          如果您打开了安全选项,在 bash 脚本中使用它是安全的:

          set -eou pipefail
          

          这是使用管道时 bash 退出状态 141 的解决方法

          tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 20 | head -1
          

          【讨论】:

            【解决方案7】:

            使用 sparse 数组来打乱字符。

            #!/bin/bash
            
            array=()
            for i in {a..z} {A..Z} {0..9}; do
                array[$RANDOM]=$i
            done
            printf %s ${array[@]::8} $'\n'
            

            (或大量随机字符串)

            #!/bin/bash
            
            b=()
            while ((${#b[@]} <= 32768)); do
                a=(); for i in {a..z} {A..Z} {0..9}; do a[$RANDOM]=$i; done; b+=(${a[@]})
            done
            tr -d  ' ' <<< ${b[@]} | fold -w 8 | head -n 4096
            

            【讨论】:

              猜你喜欢
              • 2023-03-19
              • 1970-01-01
              • 1970-01-01
              • 2012-08-07
              • 2013-10-18
              • 1970-01-01
              • 2017-08-01
              相关资源
              最近更新 更多