Jak mogę losowo ustawić linie w pliku przy użyciu standardowych narzędzi w systemie Red Hat Linux?
Nie mam z shuf
polecenia, więc szukam czegoś niczym perl
ani awk
jednego-liner, który wykonuje to samo zadanie.
Jak mogę losowo ustawić linie w pliku przy użyciu standardowych narzędzi w systemie Red Hat Linux?
Nie mam z shuf
polecenia, więc szukam czegoś niczym perl
ani awk
jednego-liner, który wykonuje to samo zadanie.
Odpowiedzi:
I jeden wiersz w Perlu, który otrzymujesz!
perl -MList::Util -e 'print List::Util::shuffle <>'
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:
#!/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
Niesprawdzone, ale mam nadzieję, że działa.
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 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?
Nie zapominajmy
sort --random-sort
brew install coreutils
wszystkie narzędzia mają przedrostek ag so: gsort --random-sort
lub gshuf
będą działać zgodnie z oczekiwaniami
gsort
i gshuf
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ępnie shuf
posortowałem to w minutę.
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 przypadku shuf
), bez względu na to, ile przydzieliłem pamięci.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
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.
$RANDOM
), ale -1 dla zniszczenia danych. Zastąpienie while read f
przez while IFS= read -r f
zapobiegnie read
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 zapobiegnie cut
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:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
A do wydrukowania tylko jednej losowej linii:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
Ale zobacz ten post, aby poznać wady Pythona random.shuffle()
. Nie będzie działać dobrze z wieloma (ponad 2080) elementami.
Powiązane z odpowiedzią Jima:
Mój ~/.bashrc
zawiera następujące elementy:
unsort ()
{
LC_ALL=C sort -R "$@"
}
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,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, że print
dzieje 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.
W ramach krótszego obejścia
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
będzie tasować pliki w miejscu. ( -n
oznacza „zawiń kod w while (<>) {...}
pętlę; BEGIN{undef$/}
powoduje , że Perl operuje na plikach w czasie zamiast na wierszach w czasie i split/^/m
jest potrzebny, ponieważ $_=<>
zostało niejawnie wykonane na całym pliku zamiast na wierszach).
FreeBSD ma własne losowe narzędzie:
cat $file | random | ...
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ść.
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
Lub pobierz z MacPorts:
$ sudo port install coreutils
i / lub
$ /opt/local//libexec/gnubin/sort --random-sort