programing

Bash 스크립트의 범위에서 난수

telebox 2023. 6. 26. 21:15
반응형

Bash 스크립트의 범위에서 난수

다음 사이에 임의 포트 번호를 생성해야 합니다.2000-65000셸 스크립트에서.는 문는입니다.$RANDOM 15비트 숫자꼼못합다니비짝서트라비트못!다합니!

PORT=$(($RANDOM%63000+2001))크기 제한이 없었다면 잘 작동했을 것입니다.

제가 이걸 어떻게 할 수 있는지 예를 들어본 사람이 있나요? 아마도 뭔가를 추출해서요./dev/urandom범위 안에 넣을까요?

shuf -i 2000-65000 -n 1

맛있게 드세요!

편집: 범위는 포함됩니다.

Mac OS X 및 FreeBSD에서는 jot을 사용할 수도 있습니다.

jot -r 1  2000 65000

페이지에 , 바맨페이에따면르지쉬,,,$RANDOM0에서 32767 사이의 분포를 나타냅니다. 즉, 부호가 없는 15비트 값입니다.을 가정하여$RANDOM 다음과 하게 분포된 없는 할 수 .

$(((RANDOM<<15)|RANDOM))

범위가 2의 거듭제곱이 아니기 때문에 간단한 모듈로 작동하면 거의 균일한 분포를 얻을 수 있지만, 30비트 입력 범위와 16비트 미만의 출력 범위를 사용할 경우에는 충분히 근접해야 합니다.

PORT=$(( ((RANDOM<<15)|RANDOM) % 63001 + 2000 ))

그리고 여기 파이썬이 있는 것이 있습니다.

randport=$(python -S -c "import random; print random.randrange(2000,63000)")

그리고 어색한 사람

awk 'BEGIN{srand();print int(rand()*(63000-2000))+2000 }'

생각나는 가장 간단한 일반적인 방법은 펄 원라이너입니다.

perl -e 'print int(rand(65000-2000)) + 2000'

항상 두 개의 숫자를 사용할 수 있습니다.

PORT=$(($RANDOM + ($RANDOM % 2) * 32768))

여전히 당신의 범위에 맞춰야 합니다.일반적인 n비트 난수법은 아니지만, 당신의 경우에 효과가 있을 것이고, 모든 것이 bash 내부에 있습니다.

정말 귀엽고 /dev/urandom에서 읽고 싶다면 다음과 같이 할 수 있습니다.

od -A n -N 2 -t u2 /dev/urandom

그러면 두 바이트를 읽고 서명되지 않은 int로 인쇄할 수 있습니다. 그래도 클리핑을 해야 합니다.

bash 전문가가 아니고 Linux 기반 bash 스크립트에서 이를 변수로 사용하려는 경우 다음을 시도해 보십시오.

VAR=$(shuf -i 200-700 -n 1)

그러면 200에서 700 사이의 범위를 얻을 수 있습니다.$VAR포괄적인

여기 또 하나 있어.저는 그것이 거의 모든 것에 효과가 있을 것이라고 생각했지만, 직장에서 제 센토스 박스에서 정렬의 무작위 옵션을 사용할 수 없습니다.

 seq 2000 65000 | sort -R | head -n 1

루비도 마찬가지:

echo $(ruby -e 'puts rand(20..65)') #=> 65 (inclusive ending)
echo $(ruby -e 'puts rand(20...65)') #=> 37 (exclusive ending)

Bash 설명서에는 매번 다음과 같이 나와 있습니다.$RANDOM를 참조하면 0에서 32767 사이의 난수가 반환됩니다.두 개의 연속된 참조를 합하면 0에서 65534 사이의 값을 얻을 수 있으며, 이 값은 2000에서 65000 사이의 임의의 숫자에 대해 원하는 63001 가능성 범위를 포함합니다.

정확한 범위로 조정하기 위해 sum modulo 63001을 사용합니다. sum modulo 63001은 0에서 63000 사이의 값을 제공합니다.이는 2000년까지 증가하면 2000년에서 65000년 사이의 원하는 임의의 숫자를 제공할 수 있습니다.이는 다음과 같이 요약할 수 있습니다.

port=$((((RANDOM + RANDOM) % 63001) + 2000))

테스트

# Generate random numbers and print the lowest and greatest found
test-random-max-min() {
    max=2000
    min=65000
    for i in {1..10000}; do
        port=$((((RANDOM + RANDOM) % 63001) + 2000))
        echo -en "\r$port"
        [[ "$port" -gt "$max" ]] && max="$port"
        [[ "$port" -lt "$min" ]] && min="$port"
    done
    echo -e "\rMax: $max, min: $min"
}

# Sample output
# Max: 64990, min: 2002
# Max: 65000, min: 2004
# Max: 64970, min: 2000

계산의 정확성

여기 계산의 정확성을 위한 완전한 브루트 포스 테스트가 있습니다.이 프로그램은 테스트 중인 계산을 사용하여 63001개의 다른 모든 가능성을 무작위로 생성하려고 합니다.--jobs매개 변수를 사용하면 실행 속도가 빨라지지만 결정론적이지 않습니다(생성된 가능성의 총합이 63001보다 낮을 수 있음).

test-all() {
    start=$(date +%s)
    find_start=$(date +%s)
    total=0; ports=(); i=0
    rm -f ports/ports.* ports.*
    mkdir -p ports
    while [[ "$total" -lt "$2" && "$all_found" != "yes" ]]; do
        port=$((((RANDOM + RANDOM) % 63001) + 2000)); i=$((i+1))
        if [[ -z "${ports[port]}" ]]; then
            ports["$port"]="$port"
            total=$((total + 1))
            if [[ $((total % 1000)) == 0 ]]; then
                echo -en "Elapsed time: $(($(date +%s) - find_start))s \t"
                echo -e "Found: $port \t\t Total: $total\tIteration: $i"
                find_start=$(date +%s)
            fi
        fi
    done
    all_found="yes"
    echo "Job $1 finished after $i iterations in $(($(date +%s) - start))s."
    out="ports.$1.txt"
    [[ "$1" != "0" ]] && out="ports/$out"
    echo "${ports[@]}" > "$out"
}

say-total() {
    generated_ports=$(cat "$@" | tr ' ' '\n' | \sed -E s/'^([0-9]{4})$'/'0\1'/)
    echo "Total generated: $(echo "$generated_ports" | sort | uniq | wc -l)."
}
total-single() { say-total "ports.0.txt"; }
total-jobs() { say-total "ports/"*; }
all_found="no"
[[ "$1" != "--jobs" ]] && test-all 0 63001 && total-single && exit
for i in {1..1000}; do test-all "$i" 40000 & sleep 1; done && wait && total-jobs

확률을 몇 의 반복이 하기 위해.p/q생성된 모든 63001개의 가능성 중 아래 표현을 사용할 수 있다고 생각합니다.를 들어, 다음은 1/2보다 큰 확률에 대한 계산이고 9/10보다 큰 확률에 대한 계산입니다.

Expression

$RANDOM0 입니다.2000에서 65000 사이의 포트가 필요합니다.63001개의 가능한 포트입니다.만약 우리가 가치관을 고수한다면,$RANDOM + 20002000년에서 33500년 사이에, 우리는 31501개의 포트를 포함합니다.동전을 던져 31501을 추가하면 33501에서 65001까지 많은 포트를 얻을 수 있습니다.그런 다음 65001을 떨어뜨리면 모든 포트에 대해 균일한 확률 분포로 필요한 정확한 커버리지를 얻을 수 있습니다.

random-port() {
    while [[ not != found ]]; do
        # 2000..33500
        port=$((RANDOM + 2000))
        while [[ $port -gt 33500 ]]; do
            port=$((RANDOM + 2000))
        done

        # 2000..65001
        [[ $((RANDOM % 2)) = 0 ]] && port=$((port + 31501)) 

        # 2000..65000
        [[ $port = 65001 ]] && continue
        echo $port
        break
    done
}

테스트

i=0
while true; do
    i=$((i + 1))
    printf "\rIteration $i..."
    printf "%05d\n" $(random-port) >> ports.txt
done

# Then later we check the distribution
sort ports.txt | uniq -c | sort -r

당신은 이걸 할 수 있다.

cat /dev/urandom|od -N2 -An -i|awk -v f=2000 -v r=65000 '{printf "%i\n", f + r * $1 / 65536}'

자세한 내용은 셸 스크립트 난수 생성기를 참조하십시오.

PORT=$(($RANDOM%63000+2001))당신이 원하는 것에 가깝다고 생각합니다.

PORT=$(($RANDOM$RANDOM$RANDOM%63000+2001))문제가 되는 크기 제한을 피합니다.변수를 하지 않기 에 이것은하게 잘 합니다. bash는 숫자 변수와 문자열 변수를 구분합니다." "자숫"$RANDOM문자열처럼 연결된 다음 계산에서 숫자로 사용할 수 있습니다.최고야!

또는 OS-X에서 다음과 같은 기능을 제공합니다.

$ gsort --random-sort

를 범에서난의 합니다.[$floor,$ceil)종속성 없음:

$(((RANDOM % $(($ceil- $floor))) + $floor))

2000 ~ 65000 사이의 100개 숫자 생성:

for i in $(seq 100); do echo $(((RANDOM % $((65000 - 2000))) + 2000));done

여러분은 당은무작번통얻수있다니습을을 통해 수 .urandom

head -200 /dev/urandom | cksum

출력:

3310670062 52870

위 번호의 한 부분을 가져오는 것.

head -200 /dev/urandom | cksum | cut -f1 -d " "

그러면 출력은

3310670062

당신의 요구를 충족시키기 위해,

head -200 /dev/urandom |cksum | cut -f1 -d " " | awk '{print $1%63000+2001}'

이것이 제가 보통 임의의 숫자를 생성하는 방법입니다.그런 다음 사용하는 포트 번호의 변수로 "NUM_1"을 사용합니다.다음은 짧은 예제 스크립트입니다.

#!/bin/bash

clear
echo 'Choose how many digits you want for port# (1-5)'
read PORT

NUM_1="$(tr -dc '0-9' </dev/urandom | head -c $PORT)"

echo "$NUM_1"

if [ "$PORT" -gt "5" ]
then
clear
echo -e "\x1b[31m Choose a number between 1 and 5! \x1b[0m"
sleep 3
clear
exit 0
fi

이것은 나에게 도움이 됩니다.

export CUDA_VISIBLE_DEVICES=$((( RANDOM % 8 )))

0 대신 1부터 시작하려면 1을 추가할 수 있습니다.

하여 100000000000-9999999 하는 것은 Bash에서 50개의 숫자를 생성하는 입니다.filename.csv

shuf -i 100000000000-999999999999 -n 50 -o filename.csv

15비트보다 큰 범위가 필요한 경우, 안전하지 않고 오래된 15비트 RANDOM을 사용하지 말고 빠르고 안전한 32비트 RANDOM을 사용하십시오.

SRANDOM은 약 2021 bash 5.1 롤아웃 이후에 사용할 수 있습니다.

"Bash 5.1과 관련하여 주목해야 할 흥미로운 추가 사항은 새로운 SRANDOM 변수입니다.SRANDOM 변수는 시스템의 엔트로피 엔진에서 임의의 데이터를 제공하므로 다시 시드할 수 없습니다.특히 SRANDOM 변수는 get random/get entropy에 의존하는 32비트 랜덤 번호를 제공합니다. /dev/random 또는 arc4 random에 대한 폴백 또는 필요한 경우 그 이후에 다른 폴백도 제공합니다."

출처: https://www.phoronix.com/news/GNU-Bash-5.1

bash에서 RANDOM과 SRANDOM의 차이점을 확인하십시오.

Bash에서 RANDOM과 SRANDOM의 차이

이 답변을 자유롭게 개선하십시오.

언급URL : https://stackoverflow.com/questions/2556190/random-number-from-a-range-in-a-bash-script

반응형