/dev/urandom의 스트림을 사용하여 지정된 수의 줄로 파일을 채우는 방법은 무엇입니까?

/dev/urandom의 스트림을 사용하여 지정된 수의 줄로 파일을 채우는 방법은 무엇입니까?

사용자가 정의한 줄 수와 줄당 문자 수를 사용하여 0과 1의 무작위 시퀀스로 파일을 채우려고 합니다.

첫 번째 단계는 0과 1의 무작위 스트림을 얻는 것입니다.

cat /dev/urandom | tr -dc 01

그런 다음 이 스트림으로 파일을 채우려고 합니다(그리고 Ctrl+C를 통해 채우기 프로세스를 종료합니다).

cat /dev/urandom | tr -dc 01 > foo

이렇게 생성된 foo 파일의 줄 수를 세어보니 0 줄이 나옵니다.

cat foo | wc -l
0

이제 흐름을 제어하려고 하므로 명명된 파이프를 만들고 그 안으로 흐름을 지정합니다. 그런 다음 줄당 문자 수와 파일의 줄 수를 제어하려는 헛된 희망으로 dd 명령을 사용하여 명명된 파이프에 연결했습니다.

makefifo namedpipe
cat /dev/urandom | tr -dc 01 > namedpipe
dd if=namedpipe of=foo bs=10 count=5

foo 파일은 실제로 50바이트의 0과 1로 채워져 있지만 행 수는 여전히 0입니다.

이 문제를 어떻게 해결합니까? 파일의 각 문자 수에 대해 개행 문자를 삽입해야 할 것 같은데, 그렇다면 어떻게 해야 할지 모르겠습니다.

답변1

어때요 fold? coreutils의 일부입니다 ...

$ tr -dc 01 < /dev/urandom | fold -w 30 | head -n 5
001010000111110001100101101101
000101110011011100100101111000
111010101011100101010110111001
111011000000000101111110110100
110011010111001110011010100011

또는 사용할 수 없는 경우 다음을 사용할 수 있습니다 awk.

$ tr -dc 01 < /dev/urandom | awk \$0=RT RS=.\{,30} | head -n 5
000100010010001110100110100111
101010010100100110111010001110
100011100101001010111101001111
010010100111100101101100010100
001101100000101001111011011000

아니면 루프로 뭔가를 할 수도 있습니다 ...

$ for line in $(seq 1 5)
> do
>     echo $(tr -dc 01 < /dev/urandom | head -c 30)
> done
100101100111011110010010100000
000000010000010010110111101011
010000111110010010000000010100
001110110001111011101011001001
001010111011000111110001100110

다른 방법이 있을 거라고 확신합니다... 맞춤 형식을 사용하는 hexdump를 사용하면 가능하다고 생각했지만 분명히 그렇지는 않았습니다... ;)

답변2

LC_ALL=C </dev/urandom \
tr '\0-\377' '[0*128][1*]' |
dd ibs=50 cbs=10 conv=unblock count=1

이것은 모든 입력 ASCII 바이트를 변환합니다(지정된 대로 모든 바이트가 됩니다 LC_ALL=C)균일하게 분포된 0 또는 1 중 하나로 변환됩니다. \0과 사이의 처음 128바이트는 \1770과 1로 변환됩니다 \200-\377. 따라서 모든 입력 바이트를 사용하면서도 1이나 0만 포함하는 무작위 순서의 시퀀스를 출력할 수 있습니다.

선택은 정확 하지만 5개의 ​​11바이트 출력 행을 얻기 위해 블록 크기를 dd설정할 필요는 없습니다.bs=(10 \n줄 이상)조각. 대신 count=1입력 바이트 블록에 대해 단일 바이트를 지정한 다음 이를 5개의 크기 변환 블록으로 분할하고 모든 후행 공백을 제거한 후 각 변환 블록에 ewline을 추가하여 cbs 크기별로 편집해야 합니다.read()ibs=50cbs=10conv=unblock\n(너는 ..하지 않았다).

그래서 실행해 보니 다음과 같이 인쇄되었습니다.

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

dd또한 한 방법과 다른 방법 간의 속도 비교를 보여주고 쓰기 유틸리티 buffer-size의 블록 요소를 읽는 경우 파이프에서 읽는 것이 문제가 되지 않음을 보여주기 위해 분담금을 약간 올렸습니다 . 그래서 먼저 다음을 수행했습니다.

time (
LC_ALL=C </dev/urandom \
tr -dc 01 |
dd ibs=4k cbs=10 conv=unblock count=k|
grep \[^01])

...표준 출력에 출력 없음(따라서 grep0 또는 1 이외의 일치 항목은 없습니다)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

위 정보를 보면 파이프라인이 시스템 호출을 기다리는 데 25.5초가 소요되었음을 알 수 있습니다. 좋아요 하지만 dd4096바이트 입력 레코드 중 1024개를 모두 읽는다는 것도 알려줍니다.완전히그리고 read()조기 반환으로 인해 잘린 부분은 없습니다. 이는 tr버퍼가 4k 청크에서 파이프아웃되기 때문입니다.

어쨌든 다음은 다른 방법으로 수행하거나 확산 스펙트럼의 모든 무작위 입력을 변환하는 것입니다.

time (
LC_ALL=C </dev/urandom \
tr '\0-\377' '[0*128][1*]' |
dd ibs=4k cbs=10 conv=unblock count=k|
grep '[^01]')

다시 한번 말하지만, 표준 출력에는 아무것도 없습니다.모두출력 은 dd0, 1 또는 개행 중 하나입니다. 이는 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

...이는 dd전체 입력 레코드 1024개 + 잘린 입력 레코드 0개를 읽는 것을 다시 보여 주지만 처리 시간은 크게 다릅니다. 여기에서 실제로 별도의 코어에서 병렬로, 집합적으로 작업할 수 있다는 것은 전체 프로세스가 0.6초 이내에 완료되는 데 걸리는 시간보다 더 많은 시간이 걸렸습니다 tr. dd이것이 더 빠를 것입니다.

답변3

생성 중에 개행을 추가하려면 다음을 수행하십시오.

{ process-without-terminating-newline ; echo ;} > outfile

기존 파일에 추가하려면 다음을 수행하십시오.

echo >> outfile

답변4

그런 다음 이 스트림으로 파일을 채우려고 합니다(그리고 Ctrl+C를 통해 채우기 프로세스를 종료합니다).

cat /dev/urandom | tr -dc 01 > foo

이렇게 생성된 foo 파일의 줄 수를 세어보니 0 줄이 나옵니다.

cat foo | wc -l
0

둘다cattr 완충기그들의 출력. Ctrl+ 를 누르면 C명령 버퍼에 남아 있는 모든 데이터가 손실됩니다 . 전체 버퍼 값이 누적되기 전에 프로그램을 아주 일찍 중단했기 tr때문에 아무것도 쓰지 않았습니다.

dd문자 장치나 파이프에서 읽는 데 사용하지 마십시오 ..

headLinux에서는 특정 바이트 수 이후의 데이터 자르기를 사용할 수 있습니다 .

i=0
while [ "$i" -lt "$number_of_lines" ]; do
  </dev/urandom tr -dc 01 | head -c "$bits_per_line"; echo
  i=$((i+1))
done >foo

또는 필요한 바이트 수를 생성하고 이를 사용하여 fold줄바꿈을 삽입합니다.

</dev/urandom tr -dc 01 |
fold -w "$bits_per_line" |
head -n "$number_of_lines"

느리지 않거나 매우 느린 모든 바이트를 거부합니다 0. 1입력의 127/128을 거부합니다. 기본 2 출력을 생성할 수 있는 표준 유틸리티는 없지만 이를 사용하여 od16진수를 생성하고 비트 단위로 변환할 수 있습니다.

</dev/urandom od -An -tx1 |
sed 's/ //g; s/0/@@@@/g; s/1/@@@`/g; s/2/@@`@/g; s/3/@@``/g; s/4/@`@@/g; s/5/@`@`/g; s/6/@``@/g; s/7/@```/g; s/8/`@@@/g; s/9/`@@`/g; s/[Aa]/`@`@/g; s/[Bb]/`@``/g; s/[Cc]/``@@/g; s/[Dd]/``@`/g; s/[Ee]/```@/g; s/[Ff]/````/g; y/@`/01/' |
fold -w "$bits_per_line" |
head -n "$number_of_lines"

그렇다면 xxd이를 사용하여 바이트를 base-2 표현으로 변환할 수 있습니다. 줄당 자릿수가 8의 배수인 경우 해당 -c옵션을 사용하여 필요할 때 줄 바꿈을 삽입하고 -l몇 줄 후에 중지하도록 할 수도 있습니다.

</dev/urandom xxd -b -c "$bytes_per_line" -l "$((bytes_per_line * number_of_lines))" |
sed -e 's/  .*//' -e 's/.*://'

관련 정보