如何在Bash中生成一个范围内的随机数?


当前回答

从/dev/random或/dev/urandom字符特殊文件读取是可行的方法。

这些设备在读取和设计时返回真正的随机数 帮助应用软件选择用于加密的安全密钥。这样的 随机数是从熵池中提取的 通过各种随机事件。{LDD3,乔纳森·科贝,亚历山德罗 Rubini和Greg Kroah-Hartman]

这两个文件是内核随机化的接口

void get_random_bytes_arch(void* buf, int nbytes)

它从硬件中抽取真正随机的字节,如果这样的功能是由硬件实现的(通常是),或者它从熵池中抽取(包括事件之间的时间,如鼠标和键盘中断,以及注册在SA_SAMPLE_RANDOM中的其他中断)。

dd if=/dev/urandom count=4 bs=1 | od -t d

这是可行的,但将不需要的输出从dd写入到stdout。下面的命令给出了我需要的整数。我甚至可以得到指定的随机位数,因为我需要调整位掩码给算术展开:

me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump 
                         -d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))

其他回答

这是我写的一个函数,它将输出一个期望范围>的随机数

描述:

随机<min> <max> 生成一个从最小到最大的随机数。最小值和最大值都可以 正数或负数,生成的随机数也可以是负数,所以 只要范围(max - min + 1)小于或等于32767。Max必须是>= min。

它的核心是:

random() {
    min="$1"
    max="$2"
    
    range=$((max - min + 1))
    rand=$((min + (RANDOM % range)))
    echo "$rand"
}

用法:

# general form: obtain a random number between min and max, inclusive
random <min> <max>

# Example: obtain a random number from -10 to 10, inclusive
random -10 10

这是从bash内置变量RANDOM中工作的,它可能只在底层使用C rand(),因为它们的最大值都是32767——请参阅:

https://en.cppreference.com/w/c/numeric/random/rand https://en.cppreference.com/w/c/numeric/random/RAND_MAX

有关bash文档,请参阅man bash:

随机 每次引用此参数时,都会生成一个0到32767之间的随机整数。随机数序列可以通过赋值给random来初始化。如果RANDOM未被设置,它将失去其特殊属性,即使随后被重置。

健壮的、可运行的、可源代码的脚本版本

这是上面随机函数的一个更健壮的版本。它包括完整的错误检查,边界检查,通过random——help或random -h提供的帮助菜单,以及一个特殊的run_check功能,允许您源或运行此脚本,以便您可以源它以将随机函数导入任何其他脚本——就像您在Python中所做的一样!

random.sh <——点击这个链接总是从我的eRCaGuy_dotfiles repo中获得最新版本。

RETURN_CODE_SUCCESS=0
RETURN_CODE_ERROR=1

HELP_STR="\
Generate a random integer number according to the usage styles below.

USAGE STYLES:
    'random'
        Generate a random number from 0 to 32767, inclusive (same as bash variable 'RANDOM').
    'random <max>'
        Generate a random number from 0 to 'max', inclusive.
    'random <min> <max>'
        Generate a random number from 'min' to 'max', inclusive. Both 'min' and 'max' can be
        positive OR negative numbers, and the generated random number can be negative too, so
        long as the range (max - min + 1) is less than or equal to 32767. Max must be >= min.

This file is part of eRCaGuy_dotfiles: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles
"

print_help() {
    echo "$HELP_STR" | less -RFX
}

# Get a random number according to the usage styles above.
# See also `utils_rand()` in utilities.c:
# https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/c/utilities.c#L176
random() {
    # PARSE ARGUMENTS

    # help menu
    if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
        print_help
        exit $RETURN_CODE_SUCCESS
    fi

    # 'random'
    if [ $# -eq 0 ]; then
        min=0
        max="none"
    # 'random max'
    elif [ $# -eq 1 ]; then
        min=0
        max="$1"
    # 'random min max'
    elif [ $# -eq 2 ]; then
        min="$1"
        max="$2"
    else
        echo "ERROR: too many arguments."
        exit "$RETURN_CODE_ERROR"
    fi

    # CHECK FOR ERRORS

    if [ "$max" = "none" ]; then
        rand="$RANDOM"
        echo "$rand"
        exit "$RETURN_CODE_SUCCESS"
    fi

    if [ "$max" -lt "$min" ]; then
        echo "ERROR: max ($max) < min ($min). Max must be >= min."
        exit "$RETURN_CODE_ERROR"
    fi

    # CALCULATE THE RANDOM NUMBER

    # See `man bash` and search for `RANDOM`. This is a limitation of that value.
    RAND_MAX=32767

    range=$((max - min + 1))
    if [ "$range" -gt "$RAND_MAX" ]; then
        echo "ERROR: the range (max - min + 1) is too large. Max allowed = $RAND_MAX, but actual" \
             "range = ($max - $min + 1) = $range."
        exit "$RETURN_CODE_ERROR"
    fi

    # NB: `RANDOM` is a bash built-in variable. See `man bash`, and also here:
    # https://stackoverflow.com/a/1195035/4561887
    rand=$((min + (RANDOM % range)))
    echo "$rand"
}

# Set the global variable `run` to "true" if the script is being **executed** (not sourced) and
# `main` should run, and set `run` to "false" otherwise. One might source this script but intend
# NOT to run it if they wanted to import functions from the script.
# See:
# 1. *****https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/bash/argument_parsing__3_advanced__gen_prog_template.sh
# 1. my answer: https://stackoverflow.com/a/70662049/4561887
# 1. https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/bash/check_if_sourced_or_executed.sh
run_check() {
    # This is akin to `if __name__ == "__main__":` in Python.
    if [ "${FUNCNAME[-1]}" == "main" ]; then
        # This script is being EXECUTED, not sourced
        run="true"
    fi
}

# ----------------------------------------------------------------------------------------------------------------------
# Main program entry point
# ----------------------------------------------------------------------------------------------------------------------

# Only run main function if this file is being executed, NOT sourced.
run="false"
run_check
if [ "$run" == "true" ]; then
    random "$@"
fi

不需要其他依赖项:

$(((RANDOM % $((upperBound - lowerBound))) + lowerBound))

随机数范围为[lowerBound,upperBound)

试试你的shell:

$ od -A n -t d -N 1 /dev/urandom

这里,-t d指定输出格式应该是带符号的十进制;-N 1表示从/dev/ urrandom读取一个字节。

我就此写了几篇文章。

https://linuxconfig.org/generating-random-numbers-in-bash-with-examples https://linuxconfig.org/random-entropy-in-bash https://www.cloudsavvyit.com/7572/how-to-generate-better-random-numbers-at-the-bash-command-line/

$ RANDOM=$(date +%s%N | cut -b10-19)
$ echo $(( $RANDOM % 113 + 13 ))

上述将给出一个介于13到125(113-1+13)之间的数字,具有合理的随机熵。

生成0到n范围内的随机数(有符号的16位整数)。$RAND变量中的结果集。例如:

#!/bin/bash

random()
{
    local range=${1:-1}

    RAND=`od -t uI -N 4 /dev/urandom | awk '{print $2}'`
    let "RAND=$RAND%($range+1)"
}

n=10
while [ $(( n -=1 )) -ge "0" ]; do
    random 500
    echo "$RAND"
done