답변:
shuf -i 2000-65000 -n 1
즐겨!
편집 : 범위가 포함됩니다.
shuf
는 괜찮을지 모르지만 실제로는 전체 입력을 순화 시킵니다. 난수를 매우 자주 생성하는 경우 나쁜 선택입니다.
time for i in {1..1000}; do shuf -i 0-$end -n 1000 > /dev/null; done
하고 비교 end=1
에 end=65535
만 반복 이상 4에 대한 초 차이 금액은 짧은 범위에 대한 25 %의 개선을 보여 주었다. 그리고 그건 많이 빠르게 OP의 배쉬 계산 만 번을 수행하는 것보다.
-n 1
해도 시간 차이는 무시할만한 수준으로 나타났습니다 end=4000000000
. 알아두면 좋은 shuf
점은 똑똑하지 않고 잘 작동 함 :-)
bash 매뉴얼 페이지에 따르면 $RANDOM
0에서 32767 사이에 배포됩니다. 즉, 부호없는 15 비트 값입니다. $RANDOM
균일하게 분포되어 있다고 가정하면 다음과 같이 균일하게 분포 된 부호없는 30 비트 정수를 만들 수 있습니다.
$(((RANDOM<<15)|RANDOM))
범위가 2의 거듭 제곱이 아니기 때문에 간단한 모듈로 연산은 거의 균일 한 분포를 제공하지만 30 비트 입력 범위와 16 비트 미만의 출력 범위를 가지고 있습니다. 이것은 실제로 충분히 가까워 야합니다.
PORT=$(( ((RANDOM<<15)|RANDOM) % 63001 + 2000 ))
$RANDOM
가 모든 쉘에서 항상 사용 가능한 것은 아닙니다. 또 다른 솔루션을 찾고
$RANDOM
두 번 참조 합니다. 를 지원 $RANDOM
하는 쉘에서는 참조 될 때마다 새 값이 생성됩니다. 따라서이 코드는 비트 0에서 14까지 하나의 $RANDOM
값으로 채우고 비트 15에서 29까지는 다른 값으로 채 웁니다. $RANDOM
균일하고 독립적 이라고 가정하면 아무것도 건너 뛰지 않고 0에서 2 ** 30-1까지의 모든 값을 포괄합니다.
여기에 파이썬이 있습니다
randport=$(python -S -c "import random; print random.randrange(2000,63000)")
하나는 awk
awk 'BEGIN{srand();print int(rand()*(63000-2000))+2000 }'
RANDOM
, POSIX에 의해 보장되지 않습니다
-S
옵션을 사용하면 결과가 나타납니다 ImportError: No module named random
. 내가 제거하면 작동합니다. 고스트 독의 의도가 무엇인지 확실하지 않습니다.
python -S -c "import random; print random.randrange(2000,63000)"
잘 작동하는 것 같습니다. 그러나 1과 2 사이의 난수를 얻으려고 할 때 항상 1을 얻는 것 같습니다 ... 생각?
가장 단순한 일반적인 방법은 펄 원 라이너입니다.
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로 인쇄합니다. 당신은 여전히 클리핑을해야합니다.
awk
에서 다른 답변의 버전을 고수해야한다
$RANDOM
0과 32767 사이의 숫자입니다. 2000과 65000 사이의 포트를 원합니다. 63001 개의 가능한 포트입니다. 2000 에서 33500$RANDOM + 2000
사이의 값을 고수하면 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}'
자세한 내용이 필요한 경우 Shell Script Random Number Generator를 참조하십시오 .
Bash 문서에 따르면$RANDOM
참조 될 때마다 0에서 32767 사이의 임의의 숫자가 반환됩니다. 두 개의 연속 참조를 합하면 0에서 65534 사이의 값을 얻습니다. 2000에서 65000 사이의 난수에 대한 63001 가능성의 범위를 포괄합니다.
정확한 범위로 조정하기 위해 합 모듈로 63001을 사용하여 0에서 63000 사이의 값을 제공합니다. 2000에서 65000 사이의 원하는 임의의 숫자를 제공하려면 2000 씩 증가하면됩니다. 다음과 같이 요약됩니다 :
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보다 큰 대 .
$RANDOM
인 정수 . 당신의 "속임수"에는 결코 달성 할 수없는 많은 가치들이 있습니다. -1
.
$RANDOM
대신 두 개의 액세스를 합산해야하며 $RANDOM
모든 액세스에서 변경되어야하기 때문에 두 개의 곱셈으로 리팩토링하지 마십시오 . 합계 버전으로 답변을 업데이트했습니다.
RANDOM+RANDOM
가 균일하게 분포 되지 않습니다.
PORT=$(($RANDOM%63000+2001))
당신이 원하는 것에 가깝습니다.
PORT=$(($RANDOM$RANDOM$RANDOM%63000+2001))
당신을 괴롭히는 크기 제한을 극복합니다. bash는 숫자 변수와 문자열 변수를 구별하지 않기 때문에 완벽하게 작동합니다. "숫자" $RANDOM
는 문자열처럼 연결 한 다음 계산에서 숫자로 사용할 수 있습니다. 놀랄 만한!
x=$(( $n%63000 )
대략 비슷합니다 x=$(( $n % 65535 )); if [ $x -gt 63000 ]; then x=63000
.
이것이 일반적으로 난수를 생성하는 방법입니다. 그런 다음 사용하는 포트 번호의 변수로 "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
shuf
비교적 최근에 생각합니다 -지난 몇 년 동안 우분투 시스템에서 보았지만 현재 RHEL / CentOS는 아닙니다.