파일에서 임의의 줄 선택
Bash 스크립트에서는 입력 파일에서 N개의 임의의 행을 선택하여 다른 파일로 출력하고 싶습니다.
이것이 어떻게 행해지는가?
와 함께 사용-n아래에 표시된 것과 같은 옵션을 얻으려면N랜덤 선:
shuf -n N input > output
로 정렬하고 파을임의정렬먼고선저다택니합하로일▁first다▁randomly▁sort▁the니선합택▁file▁pick먼을 선택합니다.100표시:
lines=100
input_file=/usr/share/dict/words
# This is the basic selection method
<$input_file sort -R | head -n $lines
# If the file has duplicates that must never cause duplicate results
<$input_file sort | uniq | sort -R | head -n $lines
# If the file has blank lines that must be filtered, use sed
<$input_file sed $'/^[ \t]*$/d' | sort -R | head -n $lines
이죠.<$input_file파이프 표준 입력으로 대체할 수 있습니다.이(()sort -R그리고.$'...\t...'갖기 위해sed탭 문자와 일치)는 GNU/리눅스 및 BSD/macOS와 함께 작동합니다.
글쎄요, 쉬프 답변에 대한 댓글에 따르면 그는 1분도 안 되어 78,000,000줄을 쉬프했습니다.
도전 수락...
편집: 제 기록을 깼습니다.
파워슈프는 0.047초 만에 그것을 했습니다.
$ time ./powershuf.py -n 10 --file lines_78000000000.txt > /dev/null
./powershuf.py -n 10 --file lines_78000000000.txt > /dev/null 0.02s user 0.01s system 80% cpu 0.047 total
왜 이렇게 빠른지, 음, 나는 전체 파일을 읽지 않고 파일 포인터를 10번만 움직이고 포인터 뒤에 줄을 인쇄합니다.
오래된 시도
먼저 78.000.000.000 줄의 파일이 필요했습니다.
seq 1 78 | xargs -n 1 -P 16 -I% seq 1 1000 | xargs -n 1 -P 16 -I% echo "" > lines_78000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000.txt > lines_78000000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000000.txt > lines_78000000000.txt
이것은 저에게 780억 줄의 새로운 줄이 있는 파일을 줍니다 ;-)
이제 쉬프 부분:
$ time shuf -n 10 lines_78000000000.txt
shuf -n 10 lines_78000000000.txt 2171.20s user 22.17s system 99% cpu 36:35.80 total
병목 현상은 CPU였고 여러 스레드를 사용하지 않았으며, 코어 1개를 100% 고정하고 나머지 15개는 사용하지 않았습니다.
Python은 제가 정기적으로 사용하는 것이기 때문에 이것을 더 빠르게 하기 위해 사용할 것입니다.
#!/bin/python3
import random
f = open("lines_78000000000.txt", "rt")
count = 0
while 1:
buffer = f.read(65536)
if not buffer: break
count += buffer.count('\n')
for i in range(10):
f.readline(random.randint(1, count))
이것은 저를 1분도 채 안되게 했습니다.
$ time ./shuf.py
./shuf.py 42.57s user 16.19s system 98% cpu 59.752 total
i9와 Samsung NVMe를 탑재한 Lenovo X1 익스트림 2세대에서 이 작업을 수행하여 읽기 및 쓰기 속도가 충분합니다.
더 빨라질 수 있다는 건 알지만 다른 사람들도 시도해 볼 수 있는 공간을 남겨두겠습니다.
선호하는 옵션은 매우 빠른 것입니다. 13개의 열, 231만 행, 2.0개의 탭으로 구분된 데이터 파일을 샘플링했습니다.GB 압축 해제.
# randomly sample select 5% of lines in file
# including header row, exclude blank lines, new seed
time \
awk 'BEGIN {srand()}
!/^$/ { if (rand() <= .05 || FNR==1) print > "data-sample.txt"}' data.txt
# awk tsv004 3.76s user 1.46s system 91% cpu 5.716 total
seq 1 100 | python3 -c 'print(__import__("random").choice(__import__("sys").stdin.readlines()))'
Arch의 할 수 있기 에: "Arch"라는 shuffle그러나 줄의 수를 제한하고 맨 페이지에 "셔플이 메모리에 입력을 읽기 때문에 매우 큰 파일에서 오류가 발생할 수 있습니다."라고 경고하는 명령줄 스위치는 없습니다.
# Function to sample N lines randomly from a file
# Parameter $1: Name of the original file
# Parameter $2: N lines to be sampled
rand_line_sampler() {
N_t=$(awk '{print $1}' $1 | wc -l) # Number of total lines
N_t_m_d=$(( $N_t - $2 - 1 )) # Number oftotal lines minus desired number of lines
N_d_m_1=$(( $2 - 1)) # Number of desired lines minus 1
# vector to have the 0 (fail) with size of N_t_m_d
echo '0' > vector_0.temp
for i in $(seq 1 1 $N_t_m_d); do
echo "0" >> vector_0.temp
done
# vector to have the 1 (success) with size of desired number of lines
echo '1' > vector_1.temp
for i in $(seq 1 1 $N_d_m_1); do
echo "1" >> vector_1.temp
done
cat vector_1.temp vector_0.temp | shuf > rand_vector.temp
paste -d" " rand_vector.temp $1 |
awk '$1 != 0 {$1=""; print}' |
sed 's/^ *//' > sampled_file.txt # file with the sampled lines
rm vector_0.temp vector_1.temp rand_vector.temp
}
rand_line_sampler "parameter_1" "parameter_2"
아래의 'c'는 입력에서 선택할 라인의 수입니다.필요에 따라 수정:
#!/bin/sh
gawk '
BEGIN { srand(); c = 5 }
c/NR >= rand() { lines[x++ % c] = $0 }
END { for (i in lines) print lines[i] }
' "$@"
언급URL : https://stackoverflow.com/questions/9245638/select-random-lines-from-a-file
'programing' 카테고리의 다른 글
| Excel에서 Mongodb를 연결하는 방법 (0) | 2023.05.22 |
|---|---|
| 소스= 호스트에 대한 ImageSourceConverter 오류 (0) | 2023.05.22 |
| ASP.NET Core 응용 프로그램이 호스팅되는 포트를 지정하는 방법은 무엇입니까? (0) | 2023.05.22 |
| 비동기 함수를 호출하는 동안 Mocha 테스트에서 시간 초과를 방지하는 방법 오류: 시간 초과가 2000ms를 초과했습니다. (0) | 2023.05.22 |
| 'div'의 알려진 속성이 아니므로 'ngIf'에 바인딩할 수 없습니다. (0) | 2023.05.22 |