LC_ALL=C </dev/urandom \
tr '\0-\377' '[0*128][1*]' |
dd ibs=50 cbs=10 conv=unblock count=1
That will convert all input ascii bytes (which will be all bytes because LC_ALL=C
is specified) into one of either 0 or 1 on an even distribution. The first 128 bytes between \0
and \177
are converted to zeroes and the \200-\377
to ones - and so you get to use all input bytes and still output randomly ordered sequences of only 1 or 0.
You were right to go with dd
, but you don't need to set your bs=
block-size to get 5 output lines of 11 bytes (10 + \n
ewline) a piece. Instead you should specify a count=1
single read()
for an input block of ibs=50
bytes which can then be divided into 5 cbs=10
sized conversion blocks, and conv=unblock
ed at cbs-size by appending a \n
ewline to each conversion block after stripping all trailing spaces (of which you have none).
So I just ran it and it printed:
1101001010
1100001001
1101110100
1011011000
1011110100
1+0 records in
0+1 records out
55 bytes (55 B) copied, 0.00176591 s, 31.1 kB/s
I also upped the ante a little bit to show a speed comparison between one method and another and to demonstrate that dd
's reading from a pipe is not an issue if you read-in at a block-factor which accounts for the writing utility's buffer-size. So I first did:
time (
LC_ALL=C </dev/urandom \
tr -dc 01 |
dd ibs=4k cbs=10 conv=unblock count=k|
grep \[^01])
...which rendered no output on stdout (so grep
matched nothing other than 0 or 1) and the following on stderr:
1024+0 records in
9011+1 records out
4613735 bytes (4.6 MB) copied, 25.8898 s, 178 kB/s
( LC_ALL=C tr -dc 01 < /dev/urandom |\
dd ibs=4k cbs=10 conv=unblock count=k |...)\
0.80s user 25.42s system 101% cpu 25.921 total
The above information tells us that the pipeline spent 25.5 secs waiting on system calls. Ok. But also it tells us that dd
read-in all 1024 of its 4096-byte sized input records completely and not a single one was truncated due to an early read()
return - and this is because tr
buffers piped output on 4k blocks.
Anyway, doing it the other way - or converting all random input on a spread spectrum, was next:
time (
LC_ALL=C </dev/urandom \
tr '\0-\377' '[0*128][1*]' |
dd ibs=4k cbs=10 conv=unblock count=k|
grep '[^01]')
Once again, there was nothing on stdout - so all of dd
's output was either one of a zero or a one or a newline - and this on stderr:
1024+0 records in
9011+1 records out
4613735 bytes (4.6 MB) copied, 0.554202 s, 8.3 MB/s
( LC_ALL=C tr '\0-\377' '[0*128][1*]' \
< /dev/urandom|dd ibs=4k cbs=10 ...)\
0.61s user 0.36s system 171% cpu 0.571 total
...which once again demonstrates that dd
read-in all 1024 complete input records + 0 truncated input records, but the processing time is significantly different. tr
and dd
are actually able to work in parallel here and together use more user time total on separate cores than it takes the whole process to complete in just under .6 seconds. That's a little faster.
tr
call withLC_ALL=C
in order for it to work.LC_ALL=C tr -dc '01' < /dev/urandom | fold -w 30 | head -n 5
worked very well here. Thank you! – Greg Sadetsky Oct 05 '20 at 17:37