Używa modułu, ale moduł jest częścią dystrybucji kodu Perla. Jeśli to nie wystarczy, możesz rozważyć zrobienie własnego.
Próbowałem użyć tego z -iflagą („edycja w miejscu”), aby edytować plik. Dokumentacja sugeruje, że to powinno działać, ale tak nie jest. Nadal wyświetla przetasowany plik na standardowe wyjście, ale tym razem usuwa oryginał. Sugeruję, żebyś go nie używał.
Rozważmy skrypt powłoki:
#!/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
Zwykle jestem fanem Perl, ale natknąłem się na ten przykład ruby który ma tę zaletę, że jest krótszy: ruby -e 'puts STDIN.readlines.shuffle'. Konieczne byłoby przetestowanie dużych danych wejściowych, aby sprawdzić, czy prędkość jest porównywalna. (działa również na OS X)
mivk
zgodnie z komentarzem poniżej, shufładuje wszystko do pamięci, więc nie działa z naprawdę dużym plikiem (mój to ~ 300GB tsv). Ten skrypt Perla również zawiódł na moim, ale bez błędu poza Killed. Masz jakiś pomysł, czy rozwiązanie Perla ładuje również wszystko do pamięci, czy jest jakiś inny problem, z którym się spotykam?
Cóż, używam gnu-coreutils 7.1 (standardowa instalacja gentoo), która ma sortowanie z tą opcją, nie jestem pewien, kiedy się pojawiła, lub czy jest w innych implementacjach.
Jim T
1
Funkcja została wprowadzona 10 grudnia 2005 r., A następnym wydaniem było 5.94, więc domyślam się, że była dostępna od tamtej wersji.
Jim T
41
W systemie OS X możesz zainstalować coreutils gnu za pomocą homebrew: brew install coreutilswszystkie narzędzia mają przedrostek ag so: gsort --random-sortlub gshufbędą działać zgodnie z oczekiwaniami
mike
3
+1 @mike. Używam Macports, a także miałem gsorti gshufzainstalowałem, kiedy to zrobiłemport install coreutils
Noah Sussman
10
To rozwiązanie jest dobre tylko wtedy, gdy twoje linie nie mają powtórzeń. Jeśli tak, wszystkie wystąpienia tej linii pojawią się obok siebie. Rozważ użycie shufzamiast tego (w systemie Linux).
Ali J
119
shuf to najlepszy sposób.
sort -Rjest boleśnie powolny. Właśnie próbowałem posortować plik 5 GB. Zrezygnowałem po 2,5 godziny. Następnie shufposortowałem to w minutę.
@benroth: Z tego, co mogę powiedzieć, przy naprawdę dużych liczbach wejściowych zwiększenie pamięci może nieco pomóc , ale ogólnie nadal jest wolne. W moich testach sortowanie pliku wejściowego o długości 1 miliona linii utworzonego za pomocą seq -f 'line %.0f' 1000000tego samego, długiego czasu (dużo, dużo dłużej niż w przypadku shuf), bez względu na to, ile przydzieliłem pamięci.
mklement0
1
@ mklement0, masz rację! Po prostu wypróbowałem to z dużo większym plikiem niż ten, który miałem wcześniej i haszowanie wydaje się być rzeczywiście wąskim gardłem.
Przeczytaj plik, uzupełnij każdą linię losową liczbą, posortuj plik według tych losowych prefiksów, a następnie wytnij przedrostki. Jednowarstwowy, który powinien pasować do każdego pół-nowoczesnego skorupy.
To działa i jest kreatywnym rozwiązaniem, ale usunie wiodące spacje w wierszach.
Chris Lutz
@Chris zmieniając ostatnie cięcie na | sed 's / ^ [^ \ t] * \ t //' powinno to naprawić
bdonlan
Uznanie dla prostoty podejścia!
Shashikant Kore
3
+1 dla zgodności z POSIX (z wyjątkiem $RANDOM), ale -1 dla zniszczenia danych. Zastąpienie while read fprzez while IFS= read -r fzapobiegnie readusunięciu wiodących i końcowych białych znaków (zobacz tę odpowiedź ) i zapobiegnie przetwarzaniu odwrotnych ukośników. Użycie losowego ciągu o stałej długości zapobiegnie cutusunięciu wiodących białych znaków. Wynik: 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: Dzięki, te sugerowane zmiany są oczywiście odpowiednie, zredagowałem swój post.
Z sortowaniem GNU coreutils -R= --random-sort, które generuje losowy skrót z każdej linii i sortuje według niego. Losowy hash nie byłby faktycznie używany w niektórych lokalizacjach w niektórych starszych (błędnych) wersjach, powodując zwracanie normalnych posortowanych danych wyjściowych, dlatego ustawiłem LC_ALL=C.
Powiązane z odpowiedzią Chrisa:
perl -MList::Util=shuffle -e'print shuffle<>'
to nieco krótsza jednolinijka. ( -Mmodule=a,b,cjest skrótem od -e 'use module qw(a b c);'.)
Powodem, dla którego prostota jest prosta -i, nie działa w przypadku tasowania w miejscu, jest to, że Perl oczekuje, że printdzieje się to w tej samej pętli, w której plik jest odczytywany, i print shuffle <>nie jest wyprowadzany, dopóki wszystkie pliki wejściowe nie zostaną odczytane i zamknięte.
będzie tasować pliki w miejscu. ( -noznacza „zawiń kod w while (<>) {...}pętlę; BEGIN{undef$/}powoduje , że Perl operuje na plikach w czasie zamiast na wierszach w czasie i split/^/mjest potrzebny, ponieważ $_=<>zostało niejawnie wykonane na całym pliku zamiast na wierszach).
Powtarzając, że sort -R nie istnieje na OS X, ale +1 dla kilku świetnych odpowiedzi Perla i ogólnie świetnej odpowiedzi.
Chris Lutz
Możesz zainstalować GNU coreutils na OS X, ale (tak jak robiłem to w przeszłości) musisz uważać, aby nie złamać wbudowanych narzędzi ... To powiedziawszy, OP jest na Redhat Linux, który zdecydowanie ma GNU standard coreutils.
Jest w / usr / games / random, więc jeśli nie masz zainstalowanych gier, nie masz szczęścia.
Możesz rozważyć zainstalowanie portów takich jak textproc / rand lub textproc / msort. Mogą być one dostępne w systemie Linux i / lub Mac OS X, jeśli problemem jest przenośność.
Odpowiedzi:
I jeden wiersz w Perlu, który otrzymujesz!
Używa modułu, ale moduł jest częścią dystrybucji kodu Perla. Jeśli to nie wystarczy, możesz rozważyć zrobienie własnego.
Próbowałem użyć tego z
-i
flagą („edycja w miejscu”), aby edytować plik. Dokumentacja sugeruje, że to powinno działać, ale tak nie jest. Nadal wyświetla przetasowany plik na standardowe wyjście, ale tym razem usuwa oryginał. Sugeruję, żebyś go nie używał.Rozważmy skrypt powłoki:
Niesprawdzone, ale mam nadzieję, że działa.
źródło
ruby -e 'puts STDIN.readlines.shuffle'
. Konieczne byłoby przetestowanie dużych danych wejściowych, aby sprawdzić, czy prędkość jest porównywalna. (działa również na OS X)shuf
ładuje wszystko do pamięci, więc nie działa z naprawdę dużym plikiem (mój to ~ 300GB tsv). Ten skrypt Perla również zawiódł na moim, ale bez błędu pozaKilled
. Masz jakiś pomysł, czy rozwiązanie Perla ładuje również wszystko do pamięci, czy jest jakiś inny problem, z którym się spotykam?Nie zapominajmy
źródło
brew install coreutils
wszystkie narzędzia mają przedrostek ag so:gsort --random-sort
lubgshuf
będą działać zgodnie z oczekiwaniamigsort
igshuf
zainstalowałem, kiedy to zrobiłemport install coreutils
shuf
zamiast tego (w systemie Linux).shuf
to najlepszy sposób.sort -R
jest boleśnie powolny. Właśnie próbowałem posortować plik 5 GB. Zrezygnowałem po 2,5 godziny. Następnieshuf
posortowałem to w minutę.źródło
sort -R
jest powolny, ponieważ oblicza skrót dla każdego wiersza. Z dokumentacji: „ Sortuj, mieszając klucze wejściowe, a następnie sortuj wartości skrótu. ”shuf
ładuje wszystko do pamięci.seq -f 'line %.0f' 1000000
tego samego, długiego czasu (dużo, dużo dłużej niż w przypadkushuf
), bez względu na to, ile przydzieliłem pamięci.Przeczytaj plik, uzupełnij każdą linię losową liczbą, posortuj plik według tych losowych prefiksów, a następnie wytnij przedrostki. Jednowarstwowy, który powinien pasować do każdego pół-nowoczesnego skorupy.
EDYCJA: włączone uwagi Richarda Hansena.
źródło
$RANDOM
), ale -1 dla zniszczenia danych. Zastąpieniewhile read f
przezwhile IFS= read -r f
zapobiegnieread
usunięciu wiodących i końcowych białych znaków (zobacz tę odpowiedź ) i zapobiegnie przetwarzaniu odwrotnych ukośników. Użycie losowego ciągu o stałej długości zapobiegniecut
usunięciu wiodących białych znaków. Wynik:cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Jednowierszowy dla Pythona:
A do wydrukowania tylko jednej losowej linii:
Ale zobacz ten post, aby poznać wady Pythona
random.shuffle()
. Nie będzie działać dobrze z wieloma (ponad 2080) elementami.źródło
Powiązane z odpowiedzią Jima:
Mój
~/.bashrc
zawiera następujące elementy:Z sortowaniem GNU coreutils
-R
=--random-sort
, które generuje losowy skrót z każdej linii i sortuje według niego. Losowy hash nie byłby faktycznie używany w niektórych lokalizacjach w niektórych starszych (błędnych) wersjach, powodując zwracanie normalnych posortowanych danych wyjściowych, dlatego ustawiłemLC_ALL=C
.Powiązane z odpowiedzią Chrisa:
to nieco krótsza jednolinijka. (
-Mmodule=a,b,c
jest skrótem od-e 'use module qw(a b c);'
.)Powodem, dla którego prostota jest prosta
-i
, nie działa w przypadku tasowania w miejscu, jest to, że Perl oczekuje, żeprint
dzieje się to w tej samej pętli, w której plik jest odczytywany, iprint shuffle <>
nie jest wyprowadzany, dopóki wszystkie pliki wejściowe nie zostaną odczytane i zamknięte.W ramach krótszego obejścia
będzie tasować pliki w miejscu. (
-n
oznacza „zawiń kod wwhile (<>) {...}
pętlę;BEGIN{undef$/}
powoduje , że Perl operuje na plikach w czasie zamiast na wierszach w czasie isplit/^/m
jest potrzebny, ponieważ$_=<>
zostało niejawnie wykonane na całym pliku zamiast na wierszach).źródło
Kiedy instaluję coreutils z homebrew
shuf
staje się dostępny jakon
.źródło
g
takshuf
stał sięgshuf
dla mnie.Mac OS X z DarwinPorts:
źródło
FreeBSD ma własne losowe narzędzie:
Jest w / usr / games / random, więc jeśli nie masz zainstalowanych gier, nie masz szczęścia.
Możesz rozważyć zainstalowanie portów takich jak textproc / rand lub textproc / msort. Mogą być one dostępne w systemie Linux i / lub Mac OS X, jeśli problemem jest przenośność.
źródło
Na OSX pobieram najnowsze z http://ftp.gnu.org/gnu/coreutils/ i coś podobnego
./configure make sudo make install
... powinien dać ci / usr / local / bin / sort --random-sort
bez zepsucia / usr / bin / sort
źródło
Lub pobierz z MacPorts:
i / lub
źródło