/dev/random
명령줄에서 (또는)을 사용하는 방법을 찾고 있습니다 . 특히, 이와 같은 스트림을 사용하여 난수 스트림(한 줄에 하나의 숫자)을 작성하는 /dev/urandom
방법을 알고 싶습니다 .stdin
stdout
나는 기계 아키텍처에서 기본적으로 지원하는 모든 숫자 유형의 난수에 관심이 있습니다. 예를 들어, 64비트 아키텍처의 경우 여기에는 64비트 부호 있는 정수와 부호 없는 정수 및 64비트 부동 소수점이 포함됩니다. 범위에 관한 한 다양한 숫자 유형의 최대 범위는 괜찮습니다.
Perl, Python 등과 같은 범용 인터프리터를 사용하여 이 모든 작업을 수행하는 방법을 알고 있지만 셸에서 "더 간단한" 도구를 사용하여 이 모든 작업을 수행하는 방법을 알고 싶습니다. (그리고 "더 쉽다"는 것은 "매우 작은 Unix 설치에서도 사용할 수 있을 가능성이 더 높다"는 의미입니다.)
기본적으로 이 문제는 명령줄에서 이진 데이터를 문자열 표현으로 변환하는 문제를 줄여줍니다. (예를 들어 다음은 작동하지 않습니다: printf '%f\n' $(head -c8 /dev/random)
.)
쉘 독립적 답변을 찾고 있습니다. 게다가 이 질문에서는 /dev/random
와 의 차이가 /dev/urandom
중요하지 않습니다. 결과의 의미가 다를 수 있더라도 한 쪽에서 작동하는 모든 절차가 다른 쪽에서도 작동할 것으로 기대합니다.
아래에 표시된 기능을 생성하기 위해 EightBitTony의 답변을 적용했습니다 toints
.
사용 예:
% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422
논평:
hexdump
대신od
내가 원하는 방식으로 출력 형식을 지정하는 더 쉬운 방법을 제공하기 때문에 이를 사용합니다 .- 하지만 짜증나게도
hexdump
64비트 정수는 지원되지 않습니다(wtf???). - 기능에 대한 인터페이스는 개선이 필요하지만(예: 인터페이스
-n5
도 수용해야 함-n 5
), 쉘 프로그래밍 기술이 부족하기 때문에 이것이 제가 신속하게 구성할 수 있는 최선입니다. (항상 그렇듯이 의견이나 개선 사항을 환영합니다.)
이 연습에서 가장 놀랐던 점은딱딱한쉘에서 프로그램을 작성하세요.기본숫자 콘텐츠(예: 16진수 부동 소수점 값 읽기 또는 최대 기본 부동 소수점 값 가져오기)...
_tonums () {
local FUNCTION_NAME=$1 BYTES=$2 CODE=$3
shift 3
local USAGE="Usage: $FUNCTION_NAME [-n <INTEGER>] [FILE...]"
local -a PREFIX
case $1 in
( -n ) if (( $# > 1 ))
then
PREFIX=( head -c $(( $2 * $BYTES )) )
shift 2
else
echo $USAGE >&2
return 1
fi ;;
( -* ) echo $USAGE >&2
return 1 ;;
( * ) PREFIX=( cat ) ;;
esac
local FORMAT=$( printf '"%%%s\\n"' $CODE )
$PREFIX "$@" | hexdump -ve $FORMAT
}
toints () {
_tonums toints 4 d "$@"
}
touints () {
_tonums touints 4 u "$@"
}
tofloats () {
_tonums tofloats 8 g "$@"
}
toprobs () {
_tonums toprobs 4 u "$@" | perl -lpe '$_/=4294967295'
}
답변1
od
을 사용하여 번호를 얻을 수 있습니다 ./dev/random
/dev/urandom
예를 들어,
2바이트 부호 없는 10진수 정수,
$ od -vAn -N2 -tu2 < /dev/urandom
24352
1바이트 부호 있는 10진수 정수,
$ od -vAn -N1 -td1 < /dev/urandom
-78
4바이트 부호 없는 10진수 정수,
$ od -vAn -N4 -tu4 < /dev/urandom
3394619386
man od
더 많은 정보를 알고 싶다면 od
.
답변2
일부 쉘(예: bash(1)
) 에는 $RANDOM
난수를 제공하는 "변수"가 있습니다.
답변3
Bash 내장 명령을 사용하는 것이 od
.
((RND=((RANDOM<<15|RANDOM)<<15|RANDOM)<<15|RANDOM))
그러면 0에서 1,152,921,504,606,846,975 사이의 임의의 숫자가 제공됩니다. 모듈식 분할을 통해 원하는 범위로 좁힐 수 있습니다.
실제적인 예로, 디스크를 대기 모드에서 깨우기 위해 하드 드라이브에서 임의의 섹터를 읽는다고 가정해 보겠습니다. 나는 이것을 할 수 있다:
#!/bin/bash
DEV=/dev/sda # Let's say that this is the device we want to spin up.
# Get the device geometry...
read -d- SIZE64 BS <<<$(blockdev --getsize64 --getbsz $DEV)
((SECTORS=SIZE64/BS)) # The total number of $BS-sized sectors on that device.
((RND=(RANDOM<<15|RANDOM)<<15|RANDOM)) # Generate a 45-bit random number.
((SECT=RND%SECTORS)) # The random sector that we will now read...
dd if=$DEV of=/dev/null bs=$BS skip=$SECT count=1 >/dev/null 2>&1
완벽한.
(참고: 이 예에서는 45비트 임의 정수이면 충분하고 60비트 임의 정수보다 조금 더 빠르다고 생각합니다.)
고쳐 쓰다:
위의 속도 주장에 대한 정량적 뒷받침을 제공하려면 다음을 수행하십시오.
~# time for i in {1..10000} ;do RND=$(od -An -N7 -tu8 /dev/urandom) ;done
real 0m45.647s
user 0m17.540s
sys 0m28.807s
~# time for i in {1..10000} ;do ((RND=((RANDOM<<15|RANDOM)<<15|RANDOM)<<15|RANDOM)) ;done
real 0m0.112s
user 0m0.105s
sys 0m0.007s
답변4
버전 5.1 또는 5.2부터 bash에는 $SRANDOM
32비트 난수를 제공하는 "변수"가 있습니다.