Bash에서 난수를 생성하는 방법은 무엇입니까?


236

Bash에서 범위 내에서 난수를 생성하는 방법은 무엇입니까?


21
얼마나 랜덤해야합니까?
bdonlan

답변:


283

사용하십시오 $RANDOM. 간단한 쉘 산술과 결합하여 종종 유용합니다. 예를 들어, 1에서 10 사이의 난수를 생성하려면 (포함) :

$ echo $((1 + RANDOM % 10))
3

실제 발생기는 variables.c함수에 brand()있습니다. 이전 버전 은 간단한 선형 생성기였습니다. 버전 4.0은 1985 년 논문을 인용bash발전기 를 사용합니다 . 이는 아마도 의사 난수의 적절한 출처임을 의미합니다. 시뮬레이션에 사용하지는 않지만 (암호화에는 사용하지는 않지만) 기본 스크립팅 작업에는 적합합니다.

심각한 임의의 숫자가 필요한 작업을 수행 중이 /dev/random거나 사용 /dev/urandom가능한 경우 :

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

21
여기서 조심하십시오. 이것은 꼬집음에는 문제가 없지만 난수에 대해 산술을 수행하면 결과의 임의성에 큰 영향을 줄 수 있습니다. 의 경우 $RANDOM % 10, $RANDOM임의의 데이터의 강력한 소스 일지라도, 8 및 9는 0-7보다 측정 가능하게 (마진은 아니지만) 덜 예측 가능하다 .
dimo414

3
@ dimo414 "마지막으로"궁금합니다. 이에 대해 더 자세히 알아볼 수있는 곳이 있습니까?
PascalVKooten

58
임의의 입력 값을 변조하여 결과를 " 비둘기 홀링 "합니다. 이후 $RANDOM의 범위는 0-32767숫자 0- 7매핑 3277다른 가능한 입력 만 8하고 9만 생성 할 수 있습니다 3276여러 가지 방법 (때문에 32768하고 32769가능하지 않습니다). 이것은 빠른 해킹의 사소한 문제이지만 결과가 균일하지 않은 것은 아닙니다. Java와 같은 임의 라이브러리 Random는 단순히 나눌 수없는 숫자를 수정하는 대신 주어진 범위에서 균일 한 난수를 올바르게 반환하는 함수를 제공합니다.
dimo414

1
@JFSebastian 매우 사실-모듈로의 문제는 나쁜 PRNG뿐만 아니라 모든 RNG 의 균일 성을 깰 수 있지만 이것을 불러 주셔서 감사합니다.
dimo414

14
문맥 상, % 10 평균 8에 대한 기본 비둘기 홀링은 0-7보다 발생할 가능성이 약 .03 % 적습니다. 쉘 스크립트가 그것보다 더 정확한 균일 난수를 요구한다면, 더 복잡하고 적절한 메커니즘을 사용하십시오.
Nelson

70

참조하십시오 $RANDOM:

$RANDOM 0-32767 범위의 의사 난수를 반환하는 내부 Bash 함수 (상수 아님)입니다. 암호화 키를 생성하는 데 사용해서는 안됩니다.


1
합니까는 32767특별한 의미가?
Jin Kwon

14
@JinKwon 327672^16 / 2 - 1부호있는 16 비트 정수의 상한입니다.
Jeffrey Martinez

@JinKwon 왜 그렇게 말하지 2^15 - 1않습니까? 동등한 것이므로 누락 된 컨텍스트가 있는지 궁금합니다.
Brett Holman

11
@BrettHolman 나는 부호있는 16 비트 정수의 "부호있는"부분을 지적하려고한다고 생각합니다. 2 ^ 16 값, postive & negative ints의 경우 반으로 나눕니다.
코디

이 답변은 질문에 대답하지 않습니다.
말괄량이

48

shuf (coreutils에서 사용 가능)를 사용할 수도 있습니다 .

shuf -i 1-100000 -n 1

범위 끝으로 vars를 어떻게 전달합니까? 나는 이것을 얻었다 :shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
dat tutbrus

1
$var범위 끝 대신 다음과 같이 추가하십시오 .var=100 && shuf -i 1-${var} -n 1
knipwim

2
로 N 개의 난수를 생성하기 쉽기 때문에이 옵션을 선호합니다 -n. 예 : 1에서 100 사이의 5 개의 난수 생성 :shuf -i 1-100 -n 5
aerijman

내가 이해하는 한 숫자는 무작위가 아닙니다. 지정 shuf -i 1-10 -n 10하면 1에서 10까지의 모든 숫자를 얻을 수 있습니다. 지정 -n 15하면 여전히 정확히 10 개의 숫자 만 한 번만 얻을 수 있습니다. 그것은 무작위 숫자를 생성하지 않고 단지 섞기 만합니다.
radlan

대체품으로 임의의 숫자를 얻으려면 : -r
Geoffrey Anderson

36

쉘에서 이것을 시도하십시오 :

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

여기 -t d에서 출력 형식이 10 진수 부호로 지정되도록 지정합니다. -N 1에서 1 바이트를 읽도록 지시 /dev/urandom합니다.


2
질문은 범위의 숫자를 묻습니다.
JSycamore

9
공백을 제거 할 수 있습니다.od -A n -t d -N 1 /dev/urandom |tr -d ' '
Robert Robert

23

당신은 또한 awk에서 임의의 숫자를 얻을 수 있습니다

awk 'BEGIN {
   # seed
   srand()
   for (i=1;i<=1000;i++){
     print int(1 + rand() * 100)
   }
}'

1
+1 알다시피, 처음에는 왜 이런 식으로하고 싶습니까?하지만 실제로는 아주 좋아합니다.
zelanix

1
시딩이 포함 된 솔루션을 제공해 주셔서 감사합니다. 나는 그것을 어디서나 찾을 수 없었다!
so.very.ti

2
파종시 +1 그것은 언급 할 가치가있을 수도 srand()의 씨앗이 현재 CPU 시간입니다. RNG를 복제 할 수 있도록 특정 시드를 지정해야하는 경우 시드 srand(x)위치를 사용 x하십시오. 또한 GNU awk의 숫자 함수 매뉴얼에서 인용 한 "다른 awk 구현은 내부적으로 다른 난수 생성기를 사용합니다." 결론은 통계 분포 생성에 관심이있는 경우 한 플랫폼에서 다른 플랫폼 (모두 실행 awk또는 gawk) 에 따라 약간의 변형이 예상된다는 것입니다 .
Cbhihe 2019

18

$ RANDOM이 있습니다. 나는 그것이 어떻게 작동하는지 정확히 모른다. 그러나 작동합니다. 테스트를 위해 다음을 수행 할 수 있습니다.

echo $RANDOM

16

나는이 트릭을 좋아한다 :

echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99

...


7
$ RANDOM의 범위는 0-32767입니다. 4-9보다 1, 2 또는 3으로 시작하는 숫자가 더 많습니다. 불균형 분포에 문제가 없으면 잘 작동합니다.
jbo5112

2
@ jbo5112 당신은 완전히 맞습니다, 마지막 자리 표시는 어떻습니까? 한 자리의 경우 $ {RANDOM : 0-1}, 두 자리의 경우 $ {RANDOM : 0-2} 에코 ...?
fraff

4
마지막 숫자를 사용하면 다소 좋지만 0과 00이 포함됩니다. 한 자리에서 0-7은 8-9보다 0.03 % 더 자주 발생합니다. 두 자리에서 0-67은 68-99보다 0.3 % 더 자주 발생합니다. 좋은 난수 분포가 필요하다면 bash를 사용하지 않기를 바랍니다. 원본 ${RANDOM:0:1}사용시 : 67.8 %의 확률로 1 또는 2 ${RANDOM:0:2}를 제공하고 0.03 %의 확률로 단일 숫자 (1 %이어야 함)를 부여 할 수 있으며, 둘 다 0.003 %의 확률로 0을 제공 할 수 있습니다 이것이 좋은 사용 사례가 여전히 있습니다 (예 : 일관성이없는 입력).
jbo5112

12

0에서 9 사이의 난수.

echo $((RANDOM%10))

2
내 나쁜, 맨 페이지를 제대로 읽지 못했습니다. $RANDOM그것은 "몇 윙어와 임의의 번호 대부분 1 ~ 3,"라고 했어야 32767 0에서만 진행)
데이비드 뉴콤

1
뭐? 다른 답변에서 언급했듯이 8과 9는 0에서 7보다 약간 덜 발생하지만 여전히 0과 9 사이입니다.
키니

6

Linux 시스템을 사용하는 경우 / dev / random 또는 / dev / urandom 에서 임의의 숫자를 얻을 수 있습니다 . 사용할 수있는 난수가 충분하지 않으면 / dev / random이 차단됩니다. 임의성에 대한 속도가 필요한 경우 / dev / urandom을 사용하십시오.

이 "파일"은 운영 체제에서 생성 된 난수로 채워집니다. 참 또는 의사 난수를 얻는 경우 시스템에서 / dev / random의 구현에 따라 다릅니다. 마우스, 하드 드라이브, 네트워크와 같은 장치 드라이버에서 수집 된 노이즈를 통해 정확한 임의의 숫자가 생성됩니다.

dd 를 사용하여 파일에서 임의의 숫자를 얻을 수 있습니다


5

나는 이러한 아이디어 중 몇 가지를 취했으며 많은 난수가 필요한 경우 신속하게 수행 해야하는 기능을 만들었습니다.

od많은 난수가 필요한 경우 통화 비용이 많이 듭니다. 대신 한 번 호출하여 / dev / urandom에서 1024 개의 난수를 저장합니다. 언제rand 호출, 마지막 난수를 반환하고 조정됩니다. 그런 다음 캐시에서 제거됩니다. 캐시가 비어 있으면 다른 1024 개의 난수를 읽습니다.

예:

rand 10; echo $RET

RET에서 0과 9 사이의 난수를 반환합니다.

declare -ia RANDCACHE
declare -i RET RAWRAND=$(( (1<<32)-1 ))

function rand(){  # pick a random number from 0 to N-1. Max N is 2^32
  local -i N=$1
  [[ ${#RANDCACHE[*]} -eq 0 ]] && { RANDCACHE=( $(od -An -tu4 -N1024 /dev/urandom) ); }  # refill cache
  RET=$(( (RANDCACHE[-1]*N+1)/RAWRAND ))  # pull last random number and scale
  unset RANDCACHE[${#RANDCACHE[*]}-1]     # pop read random number
};

# test by generating a lot of random numbers, then effectively place them in bins and count how many are in each bin.

declare -i c; declare -ia BIN

for (( c=0; c<100000; c++ )); do
  rand 10
  BIN[RET]+=1  # add to bin to check distribution
done

for (( c=0; c<10; c++ )); do
  printf "%d %d\n" $c ${BIN[c]} 
done

업데이트 : 그것은 모든 N에 대해 잘 작동하지 않습니다. 작은 N과 함께 사용하면 임의의 비트를 낭비합니다.이 경우 32 비트 임의의 숫자는 0과 9 사이의 9 개의 난수에 대해 충분한 엔트로피를 가지고 있습니다 (10 * 9 = 1,000,000,000 <= 2 * 32) 32 개의 임의의 소스 값에서 여러 개의 임의의 숫자를 추출 할 수 있습니다.

#!/bin/bash

declare -ia RCACHE

declare -i RET             # return value
declare -i ENT=2           # keep track of unused entropy as 2^(entropy)
declare -i RND=RANDOM%ENT  # a store for unused entropy - start with 1 bit

declare -i BYTES=4         # size of unsigned random bytes returned by od
declare -i BITS=8*BYTES    # size of random data returned by od in bits
declare -i CACHE=16        # number of random numbers to cache
declare -i MAX=2**BITS     # quantum of entropy per cached random number
declare -i c

function rand(){  # pick a random number from 0 to 2^BITS-1
  [[ ${#RCACHE[*]} -eq 0 ]] && { RCACHE=( $(od -An -tu$BYTES -N$CACHE /dev/urandom) ); }  # refill cache - could use /dev/random if CACHE is small
  RET=${RCACHE[-1]}              # pull last random number and scale
  unset RCACHE[${#RCACHE[*]}-1]  # pop read random number
};

function randBetween(){
  local -i N=$1
  [[ ENT -lt N ]] && {  # not enough entropy to supply ln(N)/ln(2) bits
    rand; RND=RET       # get more random bits
    ENT=MAX             # reset entropy
  }
  RET=RND%N  # random number to return
  RND=RND/N  # remaining randomness
  ENT=ENT/N  # remaining entropy
};

declare -ia BIN

for (( c=0; c<100000; c++ )); do
  randBetween 10
  BIN[RET]+=1
done

for c in ${BIN[*]}; do
  echo $c
done

나는 이것을 시도했다-100 % CPU의 10 초가 걸리고 무작위로 보이지 않는 10 개의 숫자를 인쇄했다.
Carlo Wood

나는 지금 기억한다. 이 코드는 100,000 개의 난수를 생성합니다. 그것은 임의의 것을보기 위해 각각을 'bin'에 넣습니다. 휴지통은 10 개입니다. 이 숫자는 0과 9 사이의 각 임의의 숫자가 동일 할 가능성이있는 경우 유사해야합니다. 각 숫자를 인쇄하려면 randBetween 10 후에 $ RET를 에코하십시오.
philcolbourn

od -An -tu4 -N40 /dev/urandom공백으로 구분 된 10 개의 임의의 부호없는 32 비트 정수를 생성합니다. 배열에 저장하고 나중에 사용할 수 있습니다. 귀하의 코드는 과도한 것으로 보입니다.
알리

@Ali, OP는 32 비트 또는 다른 크기의 난수를 원한다고 지정하지 않았습니다. 나와 다른 사람들은이 질문을 범위 내의 난수를 제공하는 것으로 해석했습니다. 내 랜드 기능은이 목표를 달성하고, 소진되면 프로그램을 차단시키는 엔트로피 손실을 줄입니다. / dev / urandom의 od는 2 ^ N 비트의 난수 만 반환하므로 OP는 여러 값을 배열에 저장하여이 배열에서 순차적으로 추출하여이 배열을 보충해야합니다. 아마도 이것을 답변으로 코딩하고 다른 난수 범위를 처리 할 수 ​​있습니까?
Philcolbourn

@ philcolbourn, 당신은 그가 원하는 임의의 숫자를 지정하지 않고 OP에 대해 정확하고 내 관심을 잃었습니다. 그러나 그는 " bash에서 난수 를 생성 하는 방법 ?" 내 요점은 그가 하나의 난수를 요구했다는 것입니다. 이 비평가가 이전의 주석 ( 10 개의 난수 생성)에도 적용됩니다 .
Ali

5

/ dev / random 또는 / dev / urandom 문자 특수 파일에서 읽는 것이 좋습니다.

이 장치는 읽을 때 실제로 임의의 숫자를 반환하며 응용 프로그램 소프트웨어가 암호화를위한 보안 키를 선택할 수 있도록 설계되었습니다. 이러한 난수는 다양한 난수 이벤트에 의해 제공되는 엔트로피 풀에서 추출됩니다. {LDD3, Jonathan Corbet, Alessandro 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 ))

3

이건 어떤가요:

perl -e 'print int rand 10, "\n"; '

1
암호로 안전한 난수를 위해서는 / dev / urandom에서 읽거나 Crypt :: Random 라이브러리를 사용해야합니다.
kh

3

어쩌면 나는 너무 늦었지만 jotBash의 범위 내에서 임의의 숫자를 생성하는 데 사용 하는 것은 어떻습니까?

jot -r -p 3 1 0 1

-r소수점 이하 세 자리 정밀도 ( -p) 의 난수 ( )를 생성합니다 . 이 특정 경우 0과 1 ( 1 0 1) 사이에 하나의 숫자가 표시 됩니다. 순차 데이터를 인쇄 할 수도 있습니다. 설명서에 따르면 난수의 출처는 다음과 같습니다.

시드가 지정되지 않은 경우 arc4random (3)을 통해, 시드가 제공되면 random (3)을 통해 임의의 숫자를 얻습니다.


1
설치해야 함 : sudo apt install athena-jot
xerostomus

3

@Nelson, @Barun 및 @Robert의 훌륭한 답변을 바탕으로 난수를 생성하는 Bash 스크립트가 있습니다.

  • 원하는 자릿수를 생성 할 수 있습니다.
  • 각 숫자를 개별적으로 생성 /dev/urandom되는은 훨씬 더 배쉬의보다 내장$RANDOM
#!/usr/bin/env bash

digits=10

rand=$(od -A n -t d -N 2 /dev/urandom |tr -d ' ')
num=$((rand % 10))
while [ ${#num} -lt $digits ]; do
  rand=$(od -A n -t d -N 1 /dev/urandom |tr -d ' ')
  num="${num}$((rand % 10))"
done
echo $num

정확히 내가 무엇을했는지.
프로 메테우스

2

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

1

프로그램의 임의 분기 또는 예 / 아니오; 1/0; 참 / 거짓 출력 :

if [ $RANDOM -gt 16383  ]; then              # 16383 = 32767/2 
    echo var=true/1/yes/go_hither
else 
    echo var=false/0/no/go_thither
fi

당신이 기억하는 게으른 경우 16383 :

if (( RANDOM % 2 )); then 
    echo "yes"
else 
    echo "no"
fi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.