Есть ли какая-нибудь команда Linux, которую можно использовать для выборки подмножества файла? Например, файл содержит один миллион строк, и мы хотим случайным образом выбрать только одну тысячу строк из этого файла.
Под случайным я подразумеваю, что каждая строка получает одинаковую вероятность выбора, и ни одна из выбранных линий не является повторяющейся.
head
и tail
может выбрать подмножество файла, но не случайно. Я знаю, что всегда могу написать для этого скрипт на python, но мне просто интересно, есть ли команда для этого использования.
command-line
files
command
clwen
источник
источник
Ответы:
Команда
shuf
(часть coreutils) может сделать это:И, по крайней мере, на данный момент не древние версии (добавленные в коммите от 2013 года ), которые будут использовать выборку из резервуара, когда это уместно, что означает, что она не должна исчерпывать память и использует быстрый алгоритм.
источник
sort
находится в том же разделе, и он явно не требует сортированного ввода.shuf
была введена в coreutils в версии6.0 (2006-08-15)
, и, хотите верьте, хотите нет, некоторые довольно распространенные системы (в частности, CentOS 6.5) не имеют этой версии: - |shuf -n
выполняет выборку из резервуара, по крайней мере, когда входное значение больше 8 КБ, что является размером, который они определили, лучше тестов. См. Исходный код (например, на github.com/coreutils/coreutils/blob/master/src/shuf.c#L46 ). Извините за этот очень поздний ответ. По-видимому, это новое на 6 лет назад.Если у вас очень большой файл (что является типичной причиной для взятия образца), вы обнаружите, что:
shuf
истощает память$RANDOM
не будет работать правильно, если файл превышает 32767 строкЕсли вам не нужны «ровно» n строк выборки, вы можете выбрать соотношение следующим образом:
cat input.txt | awk 'BEGIN {srand()} !/^$/ { if (rand() <= .01) print $0}' > sample.txt
При этом используется постоянная память , выборки 1% файла (если вы знаете количество строк файла, вы можете настроить этот коэффициент для выборки, близкой к ограниченному количеству строк), и работает с любым размером файла, но это не будет вернуть точное количество строк, просто статистическое соотношение.
Примечание. Код получен по адресу : https://stackoverflow.com/questions/692312/randomly-pick-lines-from-a-file-without-slurping-it-with-unix
источник
$RANDOM
не будет работать правильно для файлов, размер которых превышает 32767 строк. Утверждение «Использование$RANDOM
не достигает всего файла» является довольно широким.awk
это более дружественный ресурс, чемshuf
Похоже на вероятностное решение @ Txangel, но приближается к 100 раз быстрее.
Если вам нужна высокая производительность, точный размер выборки и вы готовы жить с пробелом в конце файла, вы можете сделать что-то вроде следующего (выборка 1000 строк из файла длиной 1 м):
.. или действительно цепочка второй метод образца вместо
head
.источник
Если
shuf -n
уловка с большими файлами исчерпывает память, и вам все еще нужен пример фиксированного размера и можно установить внешнюю утилиту, попробуйте пример :Предостережение заключается в том, что образец (1000 строк в примере) должен уместиться в памяти.
Отказ от ответственности: я являюсь автором рекомендуемого программного обеспечения.
источник
/usr/local/bin
ранее/usr/bin/
в своем пути, будьте осторожны, что MacOS поставляется со встроенным сэмплером call-stacksample
, который делает что-то совершенно другое/usr/bin/
.Не знаю ни одной команды, которая могла бы сделать то, что вы просите, но вот цикл, который я собрал, который может сделать эту работу:
sed
выберет случайную линию на каждом из 1000 проходов. Возможно, есть более эффективные решения.источник
$RANDOM
имеет диапазон от 0 до 32767. Таким образом, вы не будете получать номера строк с хорошим спредом.Вы можете сохранить следующий код в файле (например, randextract.sh) и выполнить как:
---- НАЧАТЬ ФАЙЛ ----
---- КОНЕЦ ФАЙЛА ----
источник
$RANDOM$RANDOM
не генерирует случайные числа во всем диапазоне от 0 до 3276732767 (например, он сгенерирует 1000100000, но не 1000099999).Если вы знаете количество строк в файле (например, 1e6 в вашем случае), вы можете сделать:
Если нет, вы всегда можете сделать
Это сделало бы два прохода в файле, но все же избегало бы сохранения всего файла в памяти.
Другое преимущество над GNU
shuf
заключается в том, что он сохраняет порядок строк в файле.Обратите внимание , что он принимает
n
это число строк в файле. Если вы хотите распечататьp
из первыхn
строк файла (который потенциально больше линий), вы должны были бы остановитьсяawk
наn
й строки , например:источник
Мне нравится использовать awk для этого, когда я хочу сохранить строку заголовка и когда пример может составлять приблизительный процент файла. Работает для очень больших файлов:
источник
Или вот так:
Со страницы руководства bash:
источник
Если размер вашего файла не очень велик, вы можете использовать сортировку в случайном порядке. Это занимает немного больше времени, чем shuf, но случайным образом разбирает все данные. Таким образом, вы можете легко сделать следующее, чтобы использовать head, как вы просили:
Это отсортирует файл случайным образом и даст вам первые 1000 строк.
источник
Как уже упоминалось в принятом ответе, GNU довольно хорошо
shuf
поддерживает простую случайную выборку (shuf -n
). Еслиshuf
требуются методы выборки, выходящие за рамки поддерживаемых , рассмотрите tsv-sample из утилит TSV eBay . Он поддерживает несколько дополнительных режимов выборки, включая взвешенную случайную выборку, выборку Бернулли и отдельную выборку. Производительность похожа на GNUshuf
(оба довольно быстрые). Отказ от ответственности: я автор.источник