所以我是bash的新手,在这种命令行模式下,我发现了很多用于财富命令行应用程序的文件作为其激励消息的来源:
Quote 1 line 1
Quote 1 line 2
%
Quote 2 line 1
Quote 2 line 2
Quote 2 line 3
%
我想知道如何制作bash脚本以随机打印那些引号。跳过随机部分,我真的很好奇,如何将每一行打印成用引号%
隔开的一组引号?
谢谢
答案 0 :(得分:2)
假设您在名为“ fortunes.txt”的文件中加了引号,请尝试以下纯Bash解决方案:
#! /bin/bash
declare -a fortunes=() # Array of fortunes
declare -i curr_idx=0 # Index of fortune currently being read
while IFS= read -r line ; do
[[ $line == '%' ]] && curr_idx+=1 || fortunes[curr_idx]+="$line"$'\n'
done < fortunes.txt
printf '%s\n' "${fortunes[RANDOM % ${#fortunes[*]}]}"
在我较旧的Linux系统上,该代码大约需要1秒钟才能运行在一个1兆字节的“ fortunes.txt”文件上。对于大得多的输入文件,这是不切实际的。
答案 1 :(得分:0)
由于互联网连接问题,我只读了@pjh和@paul hodges答案,我喜欢它们的简单性。我已经想出了一个凌乱的东西: (这不需要先读取整个文件行,而只需读取特定行)
#!/usr/bin/env bash
randqu_file=fortunes.txt
rando_line=$(( (RANDOM % $(wc -l < $randqu_file) + 1 )))
while [[ $(sed -n "${rando_line}p" $randqu_file) != '%' || $rando_line -eq $(wc -l < $randqu_file) ]]; do
rando_line=$((rando_line - 1))
[[ $rando_line -eq 0 ]] && break
done
rando_line=$((rando_line + 1))
while [[ $(sed -n "${rando_line}p" $randqu_file) != '%' ]]; do
sed -n "${rando_line}p" $randqu_file
rando_line=$((rando_line + 1))
[[ $rando_line -gt $(wc -l < $randqu_file) ]] && break
done
答案 2 :(得分:-1)
我是白痴,我没有正确阅读要求。
sed -n "$(grep -n % quoteFile|shuf|head -1|sed 's!:%!,/%/!')"' {/%/!p; /!%/p}' quoteFile
这是一个子shell,它使用grep -n % quoteFile
来获取%的行号,使用shuf
来对其进行随机化,使用head -1
来获取经过改组的分隔符的第一个行号,以及将sed
更改为5:%
的{{1}},作为sed外部调用的范围说明符。请注意,从双引号切换到单引号,因此我不必特别对待!(我的bash仿真很讨厌)。
外面的5,/%/
跳到sed
的%的指定行号,并打印所有没有%的行,直到看到下一个%为止。
这样做 意味着您将需要前导%,并且应删除尾随%。
shuf
perl -ne
-n表示读取每一行并对它执行代码,有点像awk。 -e定义输入表达式字符串(代码)
BEGIN {$ / = q {%}; }
在读取任何内容之前,将输入记录分隔符设置为百分号。
s / ^ \ n |%$ // g;
对于每条“行”,请从以前的任何定界符,a和训练百分号中去除前导换行符。
按@F,如果/./ ;,则$ _
如果记录中包含任何字符,则将读取的记录推入F数组中(在前导换行符之后的最后一个字符将不存在)。
END {打印$ F [int(rand(@F))]; }
在处理完所有记录后,随机打印一张。
所有输入将从任何提供的perl -ne 'BEGIN{ $/=q{%}; } s/^\n|%$//g; push @F, $_ if /./; END{ print $F[int(rand(@F))]; }' quoteFile
玩得开心。