Jak mogę losowo ustawić linie w pliku przy użyciu standardowych narzędzi w systemie Red Hat Linux?
Nie mam z shufpolecenia, więc szukam czegoś niczym perlani awkjednego-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 shufpolecenia, więc szukam czegoś niczym perlani awkjednego-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 -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
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 coreutilswszystkie narzędzia mają przedrostek ag so: gsort --random-sortlub gshufbędą działać zgodnie z oczekiwaniami
gsorti gshufzainstalowałem, kiedy to zrobiłemport install coreutils
shufzamiast tego (w systemie Linux).
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ę.
sort -Rjest 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' 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.
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 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-
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 ~/.bashrczawiera 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,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.
W ramach krótszego obejścia
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
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).
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