it-swarm.com.ru

Какой простой способ прочитать случайную строку из файла в командной строке Unix?

Какой простой способ прочитать случайную строку из файла в командной строке Unix?

231
Newbie Prog

Вы можете использовать shuf:

shuf -n 1 $FILE

Существует также утилита под названием rl. В Debian он находится в пакете randomize-lines, который делает именно то, что вы хотите, хотя и не доступен во всех дистрибутивах. На своей домашней странице он на самом деле рекомендует использовать вместо него shuf (который, я думаю, не существовал на момент создания). shuf является частью GNU coreutils, rl - нет.

rl -c 1 $FILE
343
unbeknown

Другая альтернатива:

head -$((${RANDOM} % `wc -l < file` + 1)) file | tail -1
71
PolyThinker
sort --random-sort $FILE | head -n 1

(Мне нравится вышеописанный подход к шуфу, хотя я даже не знал, что он существует, и я бы никогда не нашел этот инструмент самостоятельно)

61
Thomas Vander Stichele

Это просто 

cat file.txt | shuf -n 1

Конечно, это немного медленнее, чем "shuf -n 1 file.txt" сам по себе.

25
Yokai

perlfaq5: Как выбрать случайную строку из файла? Вот алгоритм отбора проб из книги верблюдов:

$ Perl -e 'srand; Rand($.) < 1 && ($line = $_) while <>; print $line;' file

Это имеет значительное преимущество в пространстве перед чтением всего файла. Доказательство этого метода можно найти в книге «Искусство компьютерного программирования», том 2, раздел 3.4.2, Дональда Кнута.

14
Tracker1

используя скрипт bash:

#!/bin/bash
# replace with file to read
FILE=tmp.txt
# count number of lines
NUM=$(wc - l < ${FILE})
# generate random number in range 0-NUM
let X=${RANDOM} % ${NUM} + 1
# extract X-th line
sed -n ${X}p ${FILE}
11
Paolo Tedesco

Одиночная линия bash:

sed -n $((1+$RANDOM%`wc -l test.txt | cut -f 1 -d ' '`))p test.txt

Небольшая проблема: дублирование имени файла.

4
asalamon74

Вот простой скрипт Python, который сделает эту работу:

import random, sys
lines = open(sys.argv[1]).readlines()
print(lines[random.randrange(len(lines))])

Использование:

python randline.py file_to_get_random_line_from
3
Adam Rosenfield

Другой способ использования ' awk '

awk NR==$((${RANDOM} % `wc -l < file.name` + 1)) file.name
2
Baskar

Решение, которое также работает на MacOSX и должно также работать на Linux (?):

N=5
awk 'NR==FNR {lineN[$1]; next}(FNR in lineN)' <(jot -r $N 1 $(wc -l < $file)) $file 

Куда:

  • 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 в предыдущем примере.
1
jrjc

Использование только Vanilla sed и awk и без использования $ RANDOM, простой, экономичный и достаточно быстрый «однострочный» для выбора одной строки псевдослучайно из файла с именем FILENAME выглядит следующим образом:

sed -n $(awk 'END {srand(); r=Rand()*NR; if (r<NR) {sub(/\..*/,"",r); r++;}; print r}' FILENAME)p FILENAME

(Это работает, даже если FILENAME пусто, и в этом случае строка не выводится.)

Одним из возможных преимуществ этого подхода является то, что он вызывает Rand () только один раз.

Как указано @AdamKatz в комментариях, другой возможностью будет вызвать Rand () для каждой строки:

awk 'Rand() * NR < 1 { line = $0 } END { print line }' FILENAME

(Простое доказательство правильности может быть дано на основе индукции.)

Будьте осторожны с Rand()

«В большинстве реализаций awk, включая gawk, Rand () начинает генерировать числа из одного и того же начального номера или семени при каждом запуске awk».

- https://www.gnu.org/software/gawk/manual/html_node/Numeric-Functions.html

0
peak

Вот что я обнаружил, так как моя Mac OS не использует все простые ответы. Я использовал команду jot для генерации числа, поскольку решения с переменными $ RANDOM в моем тесте не очень случайны. При тестировании моего решения у меня была большая разница в решениях, представленных в выходных данных.

  RANDOM1=`jot -r 1 1 235886`
   #range of jot ( 1 235886 ) found from earlier wc -w /usr/share/dict/web2
   echo $RANDOM1
   head -n $RANDOM1 /usr/share/dict/web2 | tail -n 1

Эхо переменной состоит в том, чтобы получить визуальное представление о сгенерированном случайном числе.

0
dreday13
#!/bin/bash

IFS=$'\n' wordsArray=($(<$1))

numWords=${#wordsArray[@]}
sizeOfNumWords=${#numWords}

while [ True ]
do
    for ((i=0; i<$sizeOfNumWords; i++))
    do
        let ranNumArray[$i]=$(( ( $RANDOM % 10 )  + 1 ))-1
        ranNumStr="$ranNumStr${ranNumArray[$i]}"
    done
    if [ $ranNumStr -le $numWords ]
    then
        break
    fi
    ranNumStr=""
done

noLeadZeroStr=$((10#$ranNumStr))
echo ${wordsArray[$noLeadZeroStr]}
0
Ken