在Unix命令行中从文件中读取随机行的简单方法是什么?

时间:2009-01-15 19:01:31

标签: linux unix random command-line

在Unix命令行中从文件中读取随机行的简单方法是什么?

13 个答案:

答案 0 :(得分:353)

您可以使用shuf

shuf -n 1 $FILE

还有一个名为rl的实用程序。在Debian中,它位于randomize-lines包中,完全符合您的要求,但并非在所有发行版中都可用。在它的主页上,它实际上建议使用shuf代替(创建它时不存在,我相信)。 shuf是GNU coreutils的一部分,rl不是。

rl -c 1 $FILE

答案 1 :(得分:72)

另一种选择:

head -$((${RANDOM} % `wc -l < file` + 1)) file | tail -1

答案 2 :(得分:64)

sort --random-sort $FILE | head -n 1

(我喜欢上面的shuf方法甚至更好 - 我甚至不知道存在,我自己也没有找到这个工具)

答案 3 :(得分:26)

这很简单。

cat file.txt | shuf -n 1

当然,这只比“shuf -n 1 file.txt”慢一点。

答案 4 :(得分:14)

perlfaq5: How do I select a random line from a file?以下是Camel Book中的油藏采样算法:

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

这在阅读整个文件的空间方面具有明显的优势。你可以在Donald E. Knuth的“计算机编程艺术,第2卷,第3.4.2节”中找到这种方法的证明。

答案 5 :(得分:11)

使用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}

答案 6 :(得分:4)

单击线:

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

轻微问题:重复文件名。

答案 7 :(得分:3)

这是一个简单的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

答案 8 :(得分:2)

使用' awk '

的另一种方法
awk NR==$((${RANDOM} % `wc -l < file.name` + 1)) file.name

答案 9 :(得分:1)

也适用于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 - &GT;保存用file1写的行号,然后在file2

  • 中打印相应的行
  • jot -r $N 1 $(wc -l < $file) - &gt;使用N-r范围内随机((1, number_of_line_in_file))绘制jot个数字。进程替换<()将使其看起来像解释器的文件,因此在前面的示例中为file1

答案 10 :(得分:0)

仅使用vanilla sed和awk,而不使用$ RANDOM,这是一种简单,节省空间且速度相当快的单线和#34;从名为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()

的警告

&#34;在大多数awk实现中,包括gawk,rand()每次运行awk时都会从相同的起始编号或种子开始生成数字。&#34;

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

答案 11 :(得分:0)

#!/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]}

答案 12 :(得分:0)

这是我发现的,因为我的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

变量的回显是为了获得生成的随机数的视觉效果。