Как я могу рандомизировать строки в файле с помощью стандартных инструментов Red Hat Linux?
У меня нет shuf
команды, так что я ищу что - то вроде perl
или awk
однострочника что совершающего ту же задачу.
Как я могу рандомизировать строки в файле с помощью стандартных инструментов Red Hat Linux?
У меня нет shuf
команды, так что я ищу что - то вроде perl
или awk
однострочника что совершающего ту же задачу.
Ответы:
И вы получите однострочник Perl!
perl -MList::Util -e 'print List::Util::shuffle <>'
Он использует модуль, но он является частью дистрибутива кода Perl. Если этого недостаточно, вы можете попробовать прокатить свой собственный.
Я пробовал использовать это с -i
флагом («редактировать на месте»), чтобы он редактировал файл. Документация предполагает, что это должно работать, но это не так. Он по-прежнему отображает перетасованный файл в стандартный вывод, но на этот раз удаляет оригинал. Я предлагаю вам не использовать его.
Рассмотрим сценарий оболочки:
#!/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
Не проверено, но, надеюсь, работает.
ruby -e 'puts STDIN.readlines.shuffle'
. Потребуется тестирование на больших входах, чтобы увидеть, сопоставима ли скорость. (также работает на OS X)
shuf
загружает все в память, поэтому он не работает с действительно огромным файлом (у меня ~ 300 ГБ tsv). Этот сценарий perl не удался и у меня, но без ошибок, кроме Killed
. Есть идеи, загружает ли решение Perl все в память или есть какая-то другая проблема, с которой я сталкиваюсь?
Хм, давай не забываем
sort --random-sort
brew install coreutils
все утилиты имеют префикс ag, поэтому: gsort --random-sort
или gshuf
будут работать должным образом,
gsort
и gshuf
установлено, когда я это делалport install coreutils
shuf
вместо этого (в Linux).
shuf
это лучший способ.
sort -R
мучительно медленно. Я просто пробовал отсортировать файл размером 5ГБ. Я сдался через 2,5 часа. Потом shuf
разобрал за минуту.
sort -R
медленная в том, что вычисляет хэш для каждой строки. Из документации: « Сортировка путем хеширования ключей ввода, а затем сортировки хеш-значений »
shuf
загружает все в память.
seq -f 'line %.0f' 1000000
занимала одинаково много времени для обработки (намного, намного дольше, чем с помощью shuf
), независимо от того, сколько памяти я выделил.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Прочтите файл, добавьте к каждой строке случайное число, отсортируйте файл по этим случайным префиксам, затем удалите префиксы. Однострочный, который должен работать в любой полусовременной оболочке.
РЕДАКТИРОВАТЬ: включены замечания Ричарда Хансена.
$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-
Однострочник для Python:
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
Но посмотрите этот пост о недостатках python random.shuffle()
. Он не будет работать со многими (более 2080) элементами.
Связано с ответом Джима:
My ~/.bashrc
содержит следующее:
unsort ()
{
LC_ALL=C sort -R "$@"
}
С сортировкой GNU coreutils, -R
= --random-sort
, которая генерирует случайный хэш каждой строки и сортирует по нему. Рандомизированный хеш на самом деле не будет использоваться в некоторых локали в некоторых более старых (глючных) версиях, в результате чего он будет возвращать нормальный отсортированный вывод, поэтому я установил LC_ALL=C
.
Относится к ответу Криса:
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
необходимо, потому что $_=<>
это было неявно выполнено с целым файлом, а не со строками.)
FreeBSD имеет свою собственную случайную утилиту:
cat $file | random | ...
Он находится в / usr / games / random, поэтому, если вы не установили игры, вам не повезло.
Вы можете рассмотреть возможность установки таких портов, как textproc / rand или textproc / msort. Они вполне могут быть доступны в Linux и / или Mac OS X, если переносимость вызывает беспокойство.
В OSX скачивание последней версии с http://ftp.gnu.org/gnu/coreutils/ и чего-то вроде
./configure сделать sudo make install
... должен дать вам / usr / local / bin / sort --random-sort
без ошибок / usr / bin / sort
Или получите его с MacPorts:
$ sudo port install coreutils
и / или
$ /opt/local//libexec/gnubin/sort --random-sort