Как к случайным образом демонстрационному подмножество файла

Наконец, я узнал решение, просто другая строка (предыдущий не нужный: wpa-ap-scan)

wpa-scan-ssid 1

Я действительно не нашел его ни в какой документации... только в сообщении форума.

42
12.01.2014, 17:03
12 ответов

shuf команда (часть coreutils) может сделать это:

shuf -n 1000 file

И по крайней мере на данный момент недревние версии (добавленный в фиксации с 2013), который будет использовать выборку водохранилища в надлежащих случаях, означая это, не должны исчерпывать память и используют алгоритм FAST.

67
27.01.2020, 19:35
  • 1
    Согласно документации, этому нужен отсортированный файл, как введено: gnu.org/software/coreutils/manual / … –  mkc 09.01.2014, 21:17
  • 2
    @Ketan, не кажется, что способ –  frostschutz 09.01.2014, 21:44
  • 3
    @Ketan, которым это находится только в неправильном разделе руководства, я верю. Обратите внимание, что даже примеры в руководстве не отсортированы. Отметьте также это sort находится в том же разделе, и он ясно не требует отсортированного входа. –  derobert 09.01.2014, 21:49
  • 4
    shuf был представлен coreutils в версии 6.0 (2006-08-15), и хотите верьте, хотите нет, некоторые обоснованно-общие-системы (CentOS 6.5 в особенности) не имеют той версии :-| –  offby1 18.11.2014, 21:59

Не знающий о любой единственной команде, которая могла сделать то, что Вы спрашиваете, но здесь являетесь циклом, который я соединил, который может сделать задание:

for i in `seq 1000`; do sed -n `echo $RANDOM % 1000000 | bc`p alargefile.txt; done > sample.txt

sed возьмет случайную строку на каждой из 1 000 передач. Возможно существуют более эффективные решения.

3
27.01.2020, 19:35
  • 1
    Действительно ли возможно получить ту же строку многократно в этом подходе? –  clwen 09.01.2014, 20:11
  • 2
    Да, довольно возможный получить тот же номер строки несколько раз. Кроме того, $RANDOM имеет диапазон между 0 и 32767. Так, Вы не доберетесь хорошо номера строки распространения. –  mkc 09.01.2014, 20:21
  • 3
    не работает - случайный, назван однажды –  Bohdan 20.08.2014, 08:20

Можно сохранить следовать код в файле (примером randextract.sh) и выполниться как:

randextract.sh file.txt

----НАЧНИТЕ ФАЙЛ----

#!/bin/sh -xv

#configuration MAX_LINES is the number of lines to extract
MAX_LINES=10

#number of lines in the file (is a limit)
NUM_LINES=`wc -l $1 | cut -d' ' -f1`

#generate a random number
#in bash the variable $RANDOM returns diferent values on each call
if [ "$RANDOM." != "$RANDOM." ]
then
    #bigger number (0 to 3276732767)
    RAND=$RANDOM$RANDOM
else
    RAND=`date +'%s'`
fi 

#The start line
START_LINE=`expr $RAND % '(' $NUM_LINES - $MAX_LINES ')'`

tail -n +$START_LINE $1 | head -n $MAX_LINES

----ФАЙЛ КОНЦА----

2
27.01.2020, 19:35
  • 1
    я не уверен, что Вы пытаетесь сделать здесь с РЭНДОМ, но $RANDOM$RANDOM не генерирует случайные числа в целом диапазоне “от 0 до 3276732767” (например, он генерирует 1000100000, но не 1000099999). –  Gilles 'SO- stop being evil' 10.01.2014, 00:37
  • 2
    OP говорит, “Каждая строка заставляет ту же вероятность быть выбранной.   … существует крошечная вероятность что последовательный блок строк быть выбранной вместе”.  I также находят, что этот ответ является загадочным, но похоже, что это извлекает блок с 10 строками последовательных строк от случайной начальной точки.  , Который не является тем, что просит OP. –  G-Man Says 'Reinstate Monica' 05.12.2016, 23:19

Или как это:

LINES=$(wc -l < file)  
RANDLINE=$[ $RANDOM % $LINES ]  
tail -n $RANDLINE  < file|head -1  

Из страницы справочника удара:

        RANDOM Each  time this parameter is referenced, a random integer
              between 0 and 32767 is generated.  The sequence of random
              numbers  may  be initialized by assigning a value to RAN‐
              DOM.  If RANDOM is unset, it loses  its  special  proper‐
              ties, even if it is subsequently reset.
1
27.01.2020, 19:35
  • 1
    , которую Это приводит к сбою плохо, если файл имеет меньше чем 32 767 строк. –  offby1 18.11.2014, 22:00
  • 2
    Это произведет одну строку из файла.   (я предполагаю, Ваша идея состоит в том, чтобы выполнить вышеупомянутые команды в цикле?)  If файл имеет больше чем 32 767 строк, затем эти команды выберут только из первых 32 767 строк.   Кроме возможной неэффективности, я не вижу большой проблемы с этим ответом, если файл имеет меньше чем 32 767 строк. –  G-Man Says 'Reinstate Monica' 05.12.2016, 23:27

Если размер файла невелик, можно использовать «Сортировка случайным образом». Это занимает немного больше времени, чем shuf, но рандомизирует все данные. Итак, вы можете легко сделать следующее, чтобы использовать head по вашему запросу:

sort -R input | head -1000 > output

Это произвольно отсортирует файл и даст вам первые 1000 строк.

1
20.08.2021, 12:59

Если у вас есть очень большой файл (что является частой причиной для выборки), вы обнаружите, что:

  1. shuf исчерпывает память
  2. Использование $ 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

33
20.08.2021, 12:59

Если вы знаете количество строк в файле (например, 1e6 в вашем случае), вы можете сделать:

awk -v n=1e6 -v p=1000 '
  BEGIN {srand()}
  rand() * n-- < p {p--; print}' < file

Если нет, вы всегда можете сделать

awk -v n="$(wc -l < file)" -v p=1000 '
  BEGIN {srand()}
  rand() * n-- < p {p--; print}' < file

Это будет сделать два прохода в файле, но при этом не хранить весь файл в памяти.

Другое преимущество по сравнению с GNU shuf состоит в том, что он сохраняет порядок строк в файле.

Обратите внимание, что предполагается, что n равно количеству строк в файле. Если вы хотите напечатать p из первых n строк файла (который потенциально может содержать больше строк), вам нужно остановить awk в строке n th, например:

awk -v n=1e6 -v p=1000 '
  BEGIN {srand()}
  rand() * n-- < p {p--; print}
  !n {exit}' < file
2
20.08.2021, 12:59

В случае, если для трюка shuf -nс большими файлами не хватает памяти, а вам по-прежнему нужен образец фиксированного размера и можно установить внешнюю утилиту, попробуйте образец:

$ sample -N 1000 < FILE_WITH_MILLIONS_OF_LINES 

Предостережение в том, что пример(1000 строк в примере )должен уместиться в памяти.

Отказ от ответственности :Я являюсь автором рекомендуемого программного обеспечения.

7
20.08.2021, 12:59

Похоже на вероятностное решение @Txangel, но почти в 100 раз быстрее.

perl -ne 'print if (rand() <.01)' huge_file.csv > sample.csv

Если вам нужна высокая производительность, точный размер выборки и вы готовы жить с промежутком в конце файла, вы можете сделать что-то вроде следующего (выборки 1000 строк из 1-метрового файла строк):

perl -ne 'print if (rand() <.0012)' huge_file.csv | head -1000 > sample.csv

.. или даже связать метод второго образца вместо head.

11
20.08.2021, 12:59

Чтобы получить один случайный блок смежных строк, используйте shufдля получения одной случайной строки, затем используйте grepдля получения блока строк после случайно выбранной строки.

$ shuf -n 1 file | grep -f - -A 10 file

Это приведет к двойному доступу к файлу. Параметр -f указывает grep получить шаблон поиска из файла, в данном случае stdin (, используя тире в качестве значения параметра f ), который представляет собой одну случайно выбранную строку из файла.

Простая функция:

function random-block {
  shuf -n 1 $1 | grep -f - -A $(($2>0?$2-1:0)) $1
}

Пример использования:

$ random-block /var/log/syslog 10

Действительно, это не будет гарантировать вывод запрошенного количества строк, если случайный выбор настолько далеко вниз, что при выборе блока остается недостаточно строк.

Расширенная функция может выглядеть так:

function random-block {
  head -n $(($(wc -l | cut -f1 -d ' ')-$2+1)) $1 | shuf -n 1 | grep -f - -A $(($2>0?$2-1:0)) $1
}

Это захватит все строки в файле, кроме последних n строк, а затем перетасует этот список строк. Это гарантирует, что grep всегда сможет выбрать запрошенное количество строк.

1
20.08.2021, 12:59

Как упоминалось в принятом ответе, GNU shufдостаточно хорошо поддерживает простую случайную выборку (shuf -n). Если необходимы методы выборки, выходящие за рамки поддерживаемых shuf, рассмотрите tsv -образец из TSV Utilities eBay. Он поддерживает несколько дополнительных режимов выборки, включая взвешенную случайную выборку, выборку Бернулли и отдельную выборку. Производительность аналогична GNU shuf(, оба довольно быстры ). Отказ от ответственности :Я являюсь автором.

0
20.08.2021, 12:59

Примерно в то время, когда этот вопрос был задан впервые, я написал утилитуsample(https://github.com/alexpreynolds/sample)на основе C99 -, которая выполняет выборку из резервуара текстовых файлов.

Мой инструмент sampleбудет использовать только 8 байтов на строку, а это означает, что очень большие файлы могут быть взяты из гораздо меньшего объема памяти.

Напротив, shufи другие инструменты, упомянутые выше, могут считывать весь файл в системную память, что часто может приводить к ошибкам out-of-memory.

Вот справочная информация, в которой кратко описаны функции:

$ sample --help
sample
  version: 1.0
  author:  Alex Reynolds

Usage: sample [--sample-size=n] [--lines-per-offset=n] [--sample-without-replacement | --sample-with-replacement] [--shuffle | --preserve-order] [--hybrid | --mmap | --cstdio] [--rng-seed=n] <newline-delimited-file>

  Performs reservoir sampling (http://dx.doi.org/10.1145/3147.3165) on very large input
  files that are delimited by newline characters. The approach used in this application
  reduces memory usage by storing a pool of byte offsets to the start of each line, instead
  of the line elements themselves.

  If the sample size (--sample-size) parameter is omitted, then the sample binary will shuffle
  the entire file.

  For text files delimited by multiples of lines, specify a --lines-per-offset value.

  Process Flags:

  --sample-size=n               | -k n    Number of samples to retrieve (n = positive integer; optional)
  --lines-per-offset=n          | -l n    Number of lines per offset (n = positive integer; optional, default=1)
  --sample-without-replacement  | -o      Sample without replacement (default)
  --sample-with-replacement     | -r      Sample with replacement (optional)
  --shuffle                     | -s      Shuffle sample written to standard output (default)
  --preserve-order              | -p      Preserve order of sample written to standard output (optional)
  --mmap                        | -m      Use memory mapping for handling input file (default)
  --cstdio                      | -c      Use C I/O routines for handling input file (optional)
  --hybrid                      | -y      Use hybrid of C I/O routines and memory mapping for handling input file (optional)
  --rng-seed=n                  | -d n    Initialize the Twister RNG with a specific seed value (n = positive integer; optional)
  --help                        | -h      Show this usage message

Для установки:

$ git clone https://github.com/alexpreynolds/sample.git
$ cd sample
$ make 
$ cp sample /usr/local/bin

Чтобы использовать его, в самом простом случае:

$ sample -k 1234 some_file.txt > some_file.sample.txt

Это рисует 1234 случайных строки из some_file.txtи записывает их в some_file.sample.txt.

0
20.08.2021, 12:59

Теги

Похожие вопросы