Red Hat Linux에서 표준 도구를 사용하여 파일의 행을 무작위 화하려면 어떻게해야합니까?


102

Red Hat Linux에서 표준 도구를 사용하여 파일의 행을 무작위 화하려면 어떻게해야합니까?

나는 shuf명령이 없기 때문에 동일한 작업을 수행하는 한 줄짜리 perl또는 awk한 줄짜리를 찾고 있습니다.


1
나는 거의 같은 질문을했습니다 [ stackoverflow.com/questions/286640/…
Steve Schnepp


나는 gcc를 모든 리눅스의 표준 도구라고 생각합니다. ; D
msb

답변:


64

그리고 Perl 한 줄짜리도 얻을 수 있습니다!

perl -MList::Util -e 'print List::Util::shuffle <>'

모듈을 사용하지만 모듈은 Perl 코드 배포의 일부입니다. 그것으로 충분하지 않다면, 당신은 자신의 롤링을 고려할 수 있습니다.

-i파일을 편집하기 위해 플래그 ( "edit-in-place") 와 함께 사용하려고 했습니다. 문서는 작동해야한다고 제안하지만 작동하지 않습니다. 여전히 셔플 된 파일을 stdout에 표시하지만 이번에는 원본을 삭제합니다. 사용하지 않는 것이 좋습니다.

쉘 스크립트를 고려하십시오.

#!/bin/sh

if [[ $# -eq 0 ]]
then
  echo "Usage: $0 [file ...]"
  exit 1
fi

for i in "$@"
do
  perl -MList::Util -e 'print List::Util::shuffle <>' $i > $i.new
  if [[ `wc -c $i` -eq `wc -c $i.new` ]]
  then
    mv $i.new $i
  else
    echo "Error for file $i!"
  fi
done

테스트되지 않았지만 잘 작동합니다.


원본 파일을 백업하려면 -i 플래그에 확장자를 붙일 수 있습니다 [ perldoc.perl.org/perlrun.html]
Steve Schnepp

저는 보통 Perl 팬이지만 더 짧아지는 이점이있는이 루비 예제를 보았습니다 : ruby -e 'puts STDIN.readlines.shuffle'. 속도가 비슷한 지 확인하려면 큰 입력에 대한 테스트가 필요합니다. (OS X에서도 작동)
mivk

아래 댓글에 따라 shuf모든 것을 메모리에로드하므로 정말 큰 파일 (내는 ~ 300GB tsv)에서는 작동하지 않습니다. 이 perl 스크립트는 내에서도 실패했지만 Killed. Perl 솔루션이 모든 것을 메모리에로드하는지, 아니면 내가 겪고있는 다른 문제가 있는지 아십니까?
seth127

211

음, 잊지 말자

sort --random-sort

1
글쎄요, 저는 gnu-coreutils 7.1 (표준 젠투 설치)을 사용하고 있는데,이 옵션으로 정렬되어 있으며 언제 나타 났는지 또는 다른 구현에 있는지 확실하지 않습니다.
Jim T

1
이 기능은 2005 년 12 월 10 일에 커밋되었으며 이후 릴리스는 5.94 였으므로 해당 버전 이후로 사용할 수 있었던 것 같습니다.
Jim T

41
OS X에서는 homebrew를 사용하여 gnu coreutils를 설치할 수 있습니다. brew install coreutils모든 유틸리티에는 ag 접두사가 붙습니다. gsort --random-sort또는 gshuf예상대로 작동합니다
mike

3
+1 @mike. 나는 MacPorts를 사용하고 또한 가지고 gsortgshuf내가 한 때 설치port install coreutils
노아 서스를

10
이 솔루션은 라인에 반복이없는 경우에만 좋습니다. 그럴 경우 해당 라인의 모든 인스턴스가 서로 옆에 나타납니다. shuf대신 사용 을 고려하십시오 (Linux에서).
Ali J

118

shuf 가장 좋은 방법입니다.

sort -R고통스럽게 느립니다. 방금 5GB 파일을 정렬하려고했습니다. 나는 2.5 시간 후에 포기했다. 그런 다음 shuf1 분 안에 정렬했습니다.


이것은 훌륭합니다. GNU coreutils에있는 것 같습니다.
ariddell

4
이유 sort -R가 느린 것은 각 줄에 대한 해시를 계산하기 때문이라고 생각합니다 . 문서에서 : " 입력 키를 해시 한 다음 해시 값을 정렬하여 정렬합니다. "
Joe Flynn

13
조심 shuf메모리에로드 다.
jfs

1
@benroth : 내가 말할 수 있듯이, 정말 많은 입력 수가 메모리를 늘리면 다소 도움이 될 수 있지만 전반적으로 여전히 느립니다. 내 테스트에서로 생성 된 100 만 줄의 입력 파일을 정렬하는 것은 할당 한 메모리 양에 관계없이 처리 seq -f 'line %.0f' 1000000하는 데 똑같이 오랜 시간 이 걸렸습니다 (를 사용하는 것보다 훨씬 더 오래 shuf).
mklement0

1
@ mklement0, 당신이 맞아요! 이전보다 훨씬 더 큰 파일로 시도했는데 해싱이 실제로 병목 현상 인 것 같습니다.
benroth

23
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-

파일을 읽고, 모든 줄 앞에 임의의 숫자를 추가하고, 임의의 접두사에 따라 파일을 정렬하고, 나중에 접두사를 자릅니다. 세미 모던 쉘에서 작동 해야하는 원 라이너.

편집 : Richard Hansen의 발언을 통합했습니다.


1
이것은 작동하고 창의적인 솔루션이지만 줄의 선행 공백을 삭제합니다.
Chris Lutz

@Chris가 마지막 컷을 | sed 's / ^ [^ \ t] * \ t //'로 변경하면 수정해야합니다
bdonlan

접근 방식의 단순성에 대한 찬사!
Shashikant Kore

3
POSIX 준수의 경우 +1 (제외 $RANDOM), 데이터 도축의 경우 -1입니다. 교체 while read f로하는 while IFS= read -r f막을 read제거하는 선행 및 후행 공백에서 (볼 이 대답 )와 슬래시 방지 처리. 고정 길이 임의 문자열을 사용하면 cut선행 공백이 삭제 되지 않습니다. 결과 : cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Richard Hansen

3
@Richard Hansen : 감사합니다. 이러한 제안 된 변경 사항은 분명히 적절합니다. 제 게시물을 편집했습니다.
ChristopheD

9

파이썬을위한 한 줄짜리 :

python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile

임의의 한 줄만 인쇄하는 경우 :

python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile

그러나 볼 이 게시물을 파이썬의의 단점에 대해 random.shuffle(). 많은 (2080 개 이상의) 요소에서 잘 작동하지 않습니다.


5

Jim의 답변과 관련이 있습니다.

내에 ~/.bashrc는 다음이 포함됩니다.

unsort ()
{
    LC_ALL=C sort -R "$@"
}

GNU coreutils의 정렬 -R= --random-sort를 사용하면 각 줄의 임의의 해시를 생성하고 정렬합니다. 무작위 화 된 해시는 일부 이전 (버기) 버전의 일부 로케일에서 실제로 사용되지 않아 정상적인 정렬 된 출력을 반환하게되므로 LC_ALL=C.


Chris의 답변과 관련이 있습니다.

perl -MList::Util=shuffle -e'print shuffle<>'

약간 더 짧은 원 라이너입니다. ( -Mmodule=a,b,c는의 약자입니다 -e 'use module qw(a b c);'.)

단순함을 제공하는 이유 -i는 내부 셔플 링에 대해 작동하지 않는 이유 는 Perl print이 파일을 읽는 동일한 루프에서 발생 하기를 기대하고 print shuffle <>모든 입력 파일을 읽고 닫을 때까지 출력하지 않기 때문입니다.

더 짧은 해결 방법으로

perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'

제자리에서 파일을 섞습니다. ( -n은 "코드를 while (<>) {...}루프로 래핑합니다 . BEGIN{undef$/}Perl이 한 번에 한 줄씩 대신 파일 한 번에 작동하도록 만들고 줄 대신 전체 파일로 암시 적으로 수행 split/^/m되었기 때문에 필요 $_=<>합니다.)


그런 종류의 반복 -R은 OS X에는 존재하지 않지만 훌륭한 Perl 답변에는 +1이며 일반적으로 훌륭한 답변입니다.
Chris Lutz

OS X에 GNU coreutils를 설치할 수 있지만 (과거에했던 것처럼) 내장 도구가 손상되지 않도록주의해야합니다. 즉, OP는 GNU가있는 Redhat Linux에 있습니다. coreutils 표준.
ephemient

3

homebrew로 coreutils를 설치할 때

brew install coreutils

shuf으로 사용할 수 있습니다 n.


양조는 모든 명령을 접두사 g그렇게 shuf되었다 gshuf나를 위해.
Jörn

^ 그들이 POSIX가 아니기 때문입니까, 아니면 완전히 꺼져 있습니까?
Dave Liu

1

DarwinPorts가있는 Mac OS X :

sudo port install unsort
cat $file | unsort | ...

1

FreeBSD에는 자체 임의 유틸리티가 있습니다.

cat $file | random | ...

/ usr / games / random에 있으므로 게임을 설치하지 않았다면 운이 좋지 않습니다.

textproc / rand 또는 textproc / msort와 같은 포트 설치를 고려할 수 있습니다. 이식성이 중요한 경우 Linux 및 / 또는 Mac OS X에서 사용할 수 있습니다.


-1

OSX에서는 http://ftp.gnu.org/gnu/coreutils/ 등에서 최신 정보를 가져옵니다.

./configure make sudo make install

... / usr / local / bin / sort --random-sort를 제공해야합니다.

/ usr / bin / sort를 엉망으로 만들지 않고


이것은 OSX (10.7)에서 나를 위해 작동하지 않았습니다. "구성 : 오류 : C 컴파일러는 실행 파일을 만들 수 없습니다"가 발생했습니다.
Dolan Antenucci 2011

@dolan 권한을 확인 하시겠습니까?
Benubird 2013 년

-1

또는 MacPorts에서 가져옵니다.

$ sudo port install coreutils

및 / 또는

$ /opt/local//libexec/gnubin/sort --random-sort
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.