파일에서 임의의 줄을 선택하십시오


240

Bash 스크립트에서 입력 파일에서 N 개의 임의 행을 골라 다른 파일로 출력하고 싶습니다.

어떻게 할 수 있습니까?


파일을 무작위로 정렬하고 첫 번째 N 줄을 선택하십시오.
Piotr Praszmo 2012


31
이것은 중복되지 않습니다-그는 N 줄 대 1 줄을 원합니다.
OneSolitaryNoob

1
관련 파일
jfs

1
sort -R특히 긴 파일의 경우 과도한 작업이 많으므로 동의 하지 않습니다. 당신이 사용할 수있는 $RANDOM, % wc -l, jot, sed -n(라 à stackoverflow.com/a/6022431/563329 ), 그리고 bash는 기능 (배열, 명령 리디렉션 등) 자신의 정의 peek실제로 5,000,000 줄 파일을 실행 기능을.
동 형사상

답변:


627

임의의 행 을 얻으려면 아래 표시된 옵션과 shuf함께 사용하십시오 .-nN

shuf -n N input > output

2
임의의 순서가 아닌 임의의 행 집합이 필요한 경우 shuf는 매우 비효율적입니다 (큰 파일의 경우). 이 답변 에서처럼 저장소 샘플링을 수행하는 것이 좋습니다 .
petrelharp

나는 이것을 500M 행 파일에서 실행하여 1,000 행을 추출했으며 13 분이 걸렸습니다. 파일은 몇 달 안에 액세스되지 않았으며 Amazon EC2 SSD 드라이브에 있습니다.
T. Brian Jones

그래서 이것은 본질적으로 더 무작위 sort -R입니까?
Mona Jalal

1
@MonaJalal은 라인을 전혀 비교할 필요가 없으므로 더 빠릅니다.
rogerdpack

결국 같은 줄이 두 번 이상 나타 납니까?
Frederick Nord

161

파일을 무작위로 정렬하고 첫 번째 100줄을 선택하십시오 .

$ sort -R input | head -n 100 >output

43
sort실제로 동일한 줄을 함께 정렬하므로 중복 줄이 있고 shuf(gnu 도구)가 설치되어 있으면 이것을 사용하는 것이 좋습니다.
케빈

22
또한 80kk 라인의 대용량 파일이있는 경우 꽤 많은 시간 을 기다려야 하지만, shuf -n매우 즉각적으로 작동합니다.
Rubens

28
Mac OS X (10.9)에서 sort -R을 사용할 수 없음
Mirko Ebert

3
@ tfb785 : sort -RGNU 옵션 일 것입니다. GNU coreutils를 설치하십시오. btw shuf는 또한 coreutils의 일부입니다.
jfs

1
@JFSebastian 코드 : sort -R input | head -n <num_lines>. 입력 파일은 279GB이며 2bi + 라인입니다. 그래도 공유 할 수 없습니다. 어쨌든, 요점은 유지할 수 있습니다 약간의 출력에 일의 무작위 선택을 할 셔플와 메모리에 줄을. 정렬은 요구 사항에 관계없이 전체 파일 을 정렬합니다 .
Rubens

18

shuf 답변에 대한 의견에 따르면 그는 1 분 안에 78 000 000 000 라인을 uff습니다.

챌린지 허용 ...

편집 : 나는 내 자신의 기록을 이겼다

powershuf는 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

이것은 78 억의 파일을 제공합니다. 바꿈이있는 ;-)

이제 shuf 부분에 대해 :

$ 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이며 여러 스레드를 사용하지 않고 100 %에서 1 코어를 고정하고 다른 15 개는 사용하지 않았습니다.

파이썬은 내가 정기적으로 사용하는 것이므로 이것을 더 빨리 만들기 위해 사용할 것입니다.

#!/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 세대에서이 작업을 수행하여 읽기 및 쓰기 속도를 크게 향상 시켰습니다.

나는 그것이 더 빨라질 수 있다는 것을 알고 있지만 다른 사람들이 시도해 볼 수있는 공간을 남겨 둘 것입니다.

라인 카운터 소스 : Luther Blissett


글쎄, powershuf의 내부 기능에 대한 설명에 따르면, 그것은 무작위 적 인 것처럼 보입니다. 한 줄은 1 자, 다른 한 줄은 20자인 두 줄로 된 파일을 사용하면 두 줄을 모두 같은 기회로 선택해야합니다. 이것은 귀하의 프로그램에는 해당되지 않는 것 같습니다.
xhienne
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.