Як я можу рандомізувати рядки у файлі за допомогою стандартних інструментів 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