Какой простой способ прочитать случайную строку из файла в командной строке Unix?
linux
unix
random
command-line
codeforester
источник
источник
Ответы:
Вы можете использовать
shuf
:Также есть утилита под названием
rl
. В Debian он входит вrandomize-lines
пакет, который делает именно то, что вы хотите, хотя и не доступен во всех дистрибутивах. На своей домашней странице он фактически рекомендует использоватьshuf
вместо этого (который, я думаю, не существовал, когда он был создан).shuf
является частью GNU coreutils,rl
не является.источник
shuf
совет, он встроен в Fedora.sort -R
определенно собирается сделать один ждать много , если дело со значительно большими файлами - 80kk линии -, в то время как,shuf -n
действует совершенно мгновенно.coreutils
из Homebrew. Может быть вызванgshuf
вместоshuf
.randomize-lines
на OS Xbrew install randomize-lines; rl -c 1 $FILE
shuf
является частью GNU Coreutils и поэтому не обязательно будет доступен (по умолчанию) в системах * BSD (или Mac?). Перл @ Tracker1 с одной строкой ниже более переносим (и, по моим тестам, немного быстрее).Другая альтернатива:
источник
(${RANDOM} << 15) + ${RANDOM}
. Это значительно уменьшает смещение и позволяет работать с файлами, содержащими до 1 миллиарда строк.+
и|
являются одинаковыми, так как${RANDOM}
это 0..32767 по определению.(Мне нравится вышеописанный подход к шуфу, хотя я даже не знал, что он существует, и я бы никогда не нашел этот инструмент самостоятельно)
источник
sort
, он не работал ни на одной из моих систем (CentOS 5.5, Mac OS 10.7.2). Кроме того, бесполезное использование кошки может быть сокращено доsort --random-sort < $FILE | head -n 1
sort -R <<< $'1\n1\n2' | head -1
с большой вероятностью вернет 1 и 2, потому чтоsort -R
сортирует повторяющиеся строки вместе. То же самое относится и кsort -Ru
, потому что он удаляет дубликаты строк.sort
перед передачейhead
.shuf
вместо этого выбирает случайные строки из файла и для меня это намного быстрее.sort --random-sort $FILE | head
бы @SteveKehlet , поскольку это позволяет ему напрямую обращаться к файлу, возможно, обеспечивая эффективную параллельную сортировку--random-sort
И-R
опции являются специфическими для GNU рода (так что они не будут работать с BSD или Mac OSsort
). GNU sort узнал эти флаги в 2005 году, поэтому вам нужен GNU coreutils 6.0 или новее (например, CentOS 6).Это просто
Конечно, это немного медленнее, чем сам по себе "shuf -n 1 file.txt".
источник
-n 1
указывается 1 строка, и вы можете изменить ее на более чем 1.shuf
Можно использовать и для других вещей; Я просто отправилps aux
иgrep
с его помощью случайным образом убить процессы, частично соответствующие имени.perlfaq5: как выбрать случайную строку из файла? Вот алгоритм отбора проб из книги верблюдов:
Это имеет значительное преимущество в пространстве перед чтением всего файла. Доказательство этого метода можно найти в книге «Искусство компьютерного программирования», том 2, раздел 3.4.2, Дональда Кнута.
источник
shuf
. Код на Perl немного быстрее (на 8% быстрее, на время пользователя, на 24% - на системное время), хотя я обнаружил, что код perl «кажется» менее случайным (я написал музыкальный автомат с его использованием).shuf
хранит весь входной файл в памяти , что является ужасной идеей, в то время как этот код хранит только одну строку, поэтому пределом этого кода является количество строк INT_MAX (2 ^ 31 или 2 ^ 63 в зависимости от вашего арка), предполагая, что любая из его выбранных потенциальных линий помещается в память.используя скрипт bash:
источник
Одиночная линия bash:
Небольшая проблема: дублирование имени файла.
источник
wc -l < test.txt
избегает необходимости трубить кcut
.Вот простой скрипт Python, который сделает эту работу:
Использование:
источник
import random, sys lines = open(sys.argv[1]).readlines()
для i в диапазоне (len (линии)): rand = random.randint (0, len (lines) -1) print lines.pop (rand),len(lines)
может привести к IndexError. Вы могли бы использоватьprint(random.choice(list(open(sys.argv[1]))))
. Существует также эффективный для памяти алгоритм отбора проб из пласта .Еще один способ использования « awk »
источник
$RANDOM
это bashism ). Вот метод чистого AWK (Мок) , используя ту же логику, @ привел код perlfaq5 Tracker1 в выше:awk 'rand() * NR < 1 { line = $0 } END { print line }' file.name
(ничего себе, это даже меньше , чем перловый код!)wc
), чтобы получить счетчик строк, а затем снова должен прочитать (часть) файл (awk
), чтобы получить содержимое заданного случайного номера строки. Ввод / вывод будет намного дороже, чем получение случайного числа. Мой код читает файл только один раз. Проблема с awk вrand()
том, что он начинается с секунд, поэтому вы получите дубликаты, если будете запускать их слишком быстро.Решение, которое также работает на MacOSX и должно также работать на Linux (?):
Куда:
N
это количество случайных строк, которые вы хотитеNR==FNR {lineN[$1]; next}(FNR in lineN) file1 file2
-> сохранить номера строк, записанные в,file1
а затем распечатать соответствующую строку вfile2
jot -r $N 1 $(wc -l < $file)
-> рисоватьN
числа случайно (-r
) в диапазоне(1, number_of_line_in_file)
сjot
. Подстановка процесса<()
сделает его похожим на файл для интерпретатора, какfile1
в предыдущем примере.источник
источник
Вот что я обнаружил, так как моя Mac OS не использует все простые ответы. Я использовал команду jot для генерации числа, поскольку решения с переменными $ RANDOM в моем тесте не очень случайны. При тестировании моего решения у меня была большая разница в решениях, представленных в выходных данных.
Отголосок переменной - получить визуальное представление о сгенерированном случайном числе.
источник
Использование только vanilla sed и awk и без использования $ RANDOM, простой, экономичный и достаточно быстрый «однострочный» для выбора одной строки псевдослучайно из файла с именем FILENAME выглядит следующим образом:
(Это работает, даже если FILENAME пусто, и в этом случае строка не выводится.)
Одним из возможных преимуществ этого подхода является то, что он вызывает rand () только один раз.
Как отметил @AdamKatz в комментариях, другой возможностью было бы вызвать rand () для каждой строки:
(Простое доказательство правильности может быть дано на основе индукции.)
Будьте о
rand()
«В большинстве реализаций awk, включая gawk, rand () начинает генерировать числа из одного и того же начального номера или seed при каждом запуске awk».
- https://www.gnu.org/software/gawk/manual/html_node/Numeric-Functions.html
источник