如何显示文本文件中的随机行?

Ana*_*Das 37 scripts text-processing

我正在尝试编写一个shell脚本。这个想法是从文本文件中随机选择一行并将其显示为 Ubuntu 桌面通知。

但是我希望每次执行脚本时都选择不同的行。有没有办法做到这一点?我不想要整个脚本。就那么简单的事情而已。

ane*_*hep 52

您可以使用shuf实用程序从文件中打印随机行

$ shuf -n 1 filename
Run Code Online (Sandbox Code Playgroud)

-n : 要打印的行数

例子:

$ shuf -n 1 /etc/passwd

git:x:998:998:git daemon user:/:/bin/bash

$ shuf -n 2 /etc/passwd

avahi:x:84:84:avahi:/:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
Run Code Online (Sandbox Code Playgroud)

  • @AnanduMDas 不,您不必用`n` 表示要打印的行数。(即您是否只想要一行或两行)。不是行号(即第一行第二行)。 (4认同)
  • +1:“shuf”位于 coreutils 中,因此默认情况下可用。注意:它将输入文件加载到内存中。[有一种不需要它的高效算法](http://askubuntu.com/a/527778/3712)。 (2认同)

g_p*_*g_p 16

您还可以使用sort命令从文件中获取随机行。

sort -R filename | head -n1
Run Code Online (Sandbox Code Playgroud)


Mal*_*ppa 8

只是为了好玩,这里是一个纯 bash 解决方案,它不使用shuf, sort, wc, sed, head,tail或任何其他外部工具。

相对于shuf变体的唯一优势是它稍微快一点,因为它是纯 bash。在我的机器上,对于 1000 行的文件,shuf变体大约需要 0.1 秒,而以下脚本大约需要 0.01 秒 ;) 因此,虽然shuf是最简单和最短的变体,但速度更快。

老实说shuf,除非高效率是一个重要问题,否则我仍然会寻求解决方案。

#!/bin/bash

FILE=file.txt

# get line count for $FILE (simulate 'wc -l')
lc=0
while read -r line; do
 ((lc++))
done < $FILE

# get a random number between 1 and $lc
rnd=$RANDOM
let "rnd %= $lc"
((rnd++))

# traverse file and find line number $rnd
i=0
while read -r line; do
 ((i++))
 [ $i -eq $rnd ] && break
done < $FILE

# output random line
printf '%s\n' "$line"
Run Code Online (Sandbox Code Playgroud)

  • @michael_n 虽然“纯 bash”方式主要用于教学和修改其他任务,但这是一个比看起来更合理的“真实”实现。Bash 是广泛可用的,但`shuf` 的 GNU Coreutils – 特定的(例如,不在 FreeBSD 10.0 中)。`sort -R` 是可移植的,但解决了一个不同的(相关的)问题:出现多行的字符串的概率等于只出现一次的字符串。(当然,`wc` 和其他实用程序仍然可以使用。)我认为这里的主要限制是它从不选择第 32768 行之后的任何内容(并且很快变得不那么随机)。 (2认同)
  • Malte Skoruppa:我看到您已将 [bash PRNG 问题移至 U&amp;L](http://unix.stackexchange.com/q/157250)。凉爽的。提示:`$((RANDOM&lt;&lt;15|RANDOM))` 在 0..2^30-1 中。@JFSebastian 是`shuf`,而不是`sort -R`,倾向于更频繁的输入。用`shuf -n 1`代替`sort -R | head -n1` 并进行比较。(顺便说一句,10^3 次迭代比 10^6 次要快,但仍然足以显示差异。)另见 [一个更粗略、更直观的演示](http://paste.ubuntu.com/8418343/) 和 [这一点愚蠢的表现它适用于所有字符串都是高频的大输入](http://paste.ubuntu.com/8418402/)。 (2认同)

c0r*_*0rp 5

假设你有文件notifications.txt。我们需要计算总行数,以确定随机生成器的范围:

$ cat notifications.txt | wc -l
Run Code Online (Sandbox Code Playgroud)

让我们写入变量:

$ LINES=$(cat notifications.txt | wc -l)
Run Code Online (Sandbox Code Playgroud)

现在要从 to 生成数字0$LINE我们将使用RANDOM变量。

$ echo $[ $RANDOM % LINES]
Run Code Online (Sandbox Code Playgroud)

让我们将其写入变量:

$  R_LINE=$(($RANDOM % LINES))
Run Code Online (Sandbox Code Playgroud)

现在我们只需要打印这个行号:

$ sed -n "${R_LINE}p" notifications.txt
Run Code Online (Sandbox Code Playgroud)

关于随机:

   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 RANDOM.  If RANDOM is unset,
          it  loses  its  special  properties,  even if it is subsequently
          reset.
Run Code Online (Sandbox Code Playgroud)

确保您的文件少于 32767 个行号。如果您需要更大的开箱即用的随机生成器,请参阅此内容

例子:

$ od -A n -t d -N 3 /dev/urandom | tr -d ' '
Run Code Online (Sandbox Code Playgroud)