Tôi đang tìm cách để sử dụng /dev/random
(hoặc /dev/urandom
) từ dòng lệnh. Cụ thể, tôi muốn biết cách sử dụng một luồng như vậy stdin
để ghi các luồng số ngẫu nhiên thành stdout
(một số trên mỗi dòng).
Tôi quan tâm đến các số ngẫu nhiên cho tất cả các loại số mà kiến trúc của máy hỗ trợ nguyên bản. Ví dụ, đối với kiến trúc 64 bit, các số này sẽ bao gồm các số nguyên có dấu và không dấu 64 bit và các số dấu phẩy động 64 bit. Theo phạm vi, phạm vi tối đa cho các loại số khác nhau sẽ làm.
Tôi biết cách thực hiện tất cả điều này với các trình thông dịch đa năng như Perl, Python, v.v., nhưng tôi muốn biết cách thực hiện điều này với các công cụ "đơn giản hơn" từ trình bao. (Theo "đơn giản hơn", ý tôi là "nhiều khả năng sẽ khả dụng ngay cả trong bản cài đặt Unix rất tối thiểu".)
Về cơ bản vấn đề làm giảm việc chuyển đổi dữ liệu nhị phân thành biểu diễn chuỗi của chúng trên dòng lệnh. (Ví dụ, điều này sẽ không làm : printf '%f\n' $(head -c8 /dev/random)
.)
Tôi đang tìm kiếm câu trả lời không rõ ràng. Ngoài ra, sự khác biệt giữa /dev/random
và /dev/urandom
không quan trọng đối với câu hỏi này. Tôi hy vọng rằng bất kỳ thủ tục nào hoạt động cho cái này sẽ hoạt động cho cái kia, ngay cả khi ngữ nghĩa của kết quả có thể khác nhau.
Tôi đã điều chỉnh câu trả lời của EightBitTony để tạo ra các hàm toints
, v.v. được hiển thị bên dưới.
Ví dụ sử dụng:
% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422
Nhận xét:
- Tôi đang sử dụng
hexdump
thayod
vì bởi vì nó cho tôi một cách dễ dàng hơn để định dạng đầu ra theo cách tôi muốn; - Mặc dù khó chịu,
hexdump
không hỗ trợ số nguyên 64 bit (wtf ???); - Giao diện chức năng nhu cầu công việc (ví dụ như họ nên chấp nhận
-n5
cũng như-n 5
), nhưng với tội nghiệp lập trình shell skillz của tôi, đây là tốt nhất mà tôi có thể đặt lại với nhau một cách nhanh chóng. (Bình luận / cải tiến chào mừng, như mọi khi.)
Điều ngạc nhiên lớn mà tôi có được từ bài tập này là phát hiện ra việc lập trình trên vỏ các công cụ số cơ bản nhất khó như thế nào (ví dụ đọc một số thập lục phân hoặc lấy giá trị float gốc tối đa) ...
_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'
}
tr -cs '[:digit:]' '[\n*]' </dev/urandom
chỉ cung cấp cho bạn số nguyên.