Як я можу рандомізувати рядки у файлі за допомогою стандартних інструментів Red Hat Linux?
У мене немає shuf
команди, тому я шукаю щось на кшталт perl
або awk
одного вкладиша, що виконує те саме завдання.
Як я можу рандомізувати рядки у файлі за допомогою стандартних інструментів Red Hat Linux?
У мене немає shuf
команди, тому я шукаю щось на кшталт perl
або awk
одного вкладиша, що виконує те саме завдання.
Відповіді:
І один-лайнер Perl ви отримаєте!
perl -MList::Util -e 'print List::Util::shuffle <>'
Він використовує модуль, але модуль є частиною розподілу коду Perl. Якщо це недостатньо добре, ви можете розглянути можливість прокатки власних.
Я спробував використовувати це з -i
прапором ("редагувати на місці"), щоб він зміг редагувати файл. Документація підказує, що вона повинна працювати, але це не так. Він все ще відображає перетасований файл до 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
Неперевірений, але, сподіваємось, працює.
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-
Прочитайте файл, додайте кожен рядок зі випадковим числом, сортуйте файл за тими випадковими префіксами, виріжте префікси згодом. Однолінійний, який повинен працювати в будь-якій напівмодерній оболонці.
EDIT: включено зауваження Річарда Хансена.
$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 -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) елементами.
Пов'язане з відповіддю Джима:
Моє ~/.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 - випадковий сортування
не псуючи / usr / bin / sort
Або отримати його від MacPorts:
$ sudo port install coreutils
та / або
$ /opt/local//libexec/gnubin/sort --random-sort