只是想知道,因为我上个月鞭打了这个。
#!/usr/bin/bash
# Collects all of the args, make sure to seperate with ','
IN="$*"
# Takes everything before a ',' and places them each on a single line of tmp file
echo $IN | sed 's/,/\n/g' > /tmp/pick.a.random.word.or.phrase
# Obvious vars are obvious
WORDFILE="/tmp/pick.a.random.word.or.phrase"
# Pick only one of the vars
NUMWORDS=1
## Picks a random line from tmp file
#Number of lines in $WORDFILE
tL=`awk 'NF!=0 {++c} END {print c}' $WORDFILE`
# Expand random
RANDOM_CMD='od -vAn -N4 -tu4 /dev/urandom'
for i in `seq $NUMWORDS`
do
rnum=$((`${RANDOM_CMD}`%$tL+1))
sed -n "$rnum p" $WORDFILE | tr '\n' ' '
done
printf "\n"
rm /tmp/pick.a.random.word.or.phrase
主要是我问:
答案 0 :(得分:2)
在我看来,命令行参数处理是奇怪的。为什么不使用普通的命令行参数?这使问题变得微不足道:
#!/usr/bin/bash
shuf -en1 "$@"
当然,您可以使用shuf -en1
,这只是九次击键:
$ shuf -en1 word another_word "random phrase"
another_word
$ shuf -en1 word another_word "random phrase"
word
$ shuf -en1 word another_word "random phrase"
another_word
$ shuf -en1 word another_word "random phrase"
random phrase
shuf
命令行标志:
-e Shuffle command line arguments instead of lines in a file/stdin
-n1 Produce only the first random line (or argument in this case)
如果你真的坚持一起运行参数然后用逗号分隔它们,你可以使用以下内容。与原始版本一样,如果参数中的某些单词可以进行全局展开,则会出现意外行为,所以我真的不推荐它:
#!/usr/bin/bash
IFS=, read -ra args <<<"$*"
echo $(shuf -en1 "${args[@]}")
第一行组合了参数,然后将逗号的结果拆分为数组args
。 (要读取的-a
选项。)由于字符串以逗号分隔,因此保留空格(例如,尽管由参数连接自动插入);为了删除空格,我通过不引用命令扩展来对shuf
的结果进行分词。
答案 1 :(得分:0)
您可以使用shuff缩短脚本并删除临时文件。
#!/usr/bin/bash
# Collects all of the args, make sure to seperate with ','
IN="$*"
# Takes everything before a ',' and places them in an array
words=($(echo $IN | sed 's/,/ /g'))
# Get random indexi in range: 0, length of array: words
index=$(shuf -i 0-"${#words[@]}" -n 1)
# Print the random index
echo ${words[$index]}
如果您不想使用shuff,也可以使用$RANDOM
:
#!/usr/bin/bash
# Collects all of the args, make sure to seperate with ','
IN="$*"
# Takes everything before a ',' and places them in an array
words=($(echo $IN | sed 's/,/ /g'))
# Print the random index
echo ${words[$RANDOM % ${#words[@]}]}
答案 2 :(得分:0)
shuf
正是如此,但是使用多个命令参数而不是单个逗号分隔的参数。
shuf -n1 -e arg1 arg2 ...
-n1
选项表示只选择一个元素。 -e
选项表示元素将作为参数传递(而不是通过标准输入)。
您的脚本只需要用$*
中的空格替换逗号。我们可以使用bash参数替换来执行此操作:
#!/usr/bin/bash
shuf -n1 -e ${*//,/ }
这不适用于带有嵌入空格的元素。
答案 3 :(得分:0)
是不是像在1和$#
之间随机生成数字一样简单,只是回显相应的参数?这取决于你拥有的东西;你对'收集论点;确保用逗号分隔'不清楚,因为赋值对逗号没有任何作用 - 并且你没有显示你如何调用命令。
我只是简单地从问题中产生随机数生成:它在我的Mac上运行正常,在连续运行时生成值42,405,691和1,817,261,076。
n=$(( $(od -vAn -N4 -tu4 /dev/urandom) % $# + 1 ))
eval echo "\${$n}"
如果你真的下定决心,你甚至可以将它减少到一行:
eval echo "\${$(( $(od -vAn -N4 -tu4 /dev/urandom) % $# + 1 ))}"
eval
的使用是安全的,因为它不涉及用户输入。在$#
为0时,脚本应该检查是否提供了至少一个参数以防止被零除错误。代码执行数据移动的绝对最小值 - 与在某些方面对数据进行混洗的解决方案形成对比方式。
如果将其打包在脚本random_selection
中,那么我可以运行:
$ bash random_selection Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Feb
$ bash random_selection Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Oct
$ bash random_selection Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Nov
$
如果参数的总数足够大,以至于你的参数空间不足,那么你需要再考虑一下,但现有代码中存在这种限制。
选择略微偏向于列表中较早的条目;你必须更好地拒绝非常接近范围内最大值的随机数。对于随机32位无符号值,如果它大于$# * (0xFFFFFFFF / $#)
,则应生成另一个随机数。