Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 从args中选择随机条目的更好方法?_Linux_Bash - Fatal编程技术网

Linux 从args中选择随机条目的更好方法?

Linux 从args中选择随机条目的更好方法?,linux,bash,Linux,Bash,我只是想知道,因为我上个月突然想到了这个 #!/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.phra

我只是想知道,因为我上个月突然想到了这个

#!/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
我主要问:

  • 我需要一个tmp文件吗
  • 有没有办法在一行中使用另一个程序来实现这一点
  • 如何尽可能地浓缩
  • 您可以使用来缩短脚本并删除临时文件

    #!/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[@]}]}
    
    您可以使用来缩短脚本并删除临时文件

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

    在我看来,命令行参数处理很奇怪。为什么不直接使用普通的命令行参数呢?这使得问题变得微不足道:

    #!/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)
    
    如果您确实坚持将参数一起运行,然后用逗号分隔,那么可以使用以下方法。与您的原始版本一样,如果参数中的某个单词可以进行glob扩展,那么它将表现出意外的行为,因此我真的不推荐它:

    #!/usr/bin/bash
    IFS=, read -ra args <<<"$*"
    echo $(shuf -en1 "${args[@]}")
    
    #/usr/bin/bash
    
    在我看来,IFS=,read-ra args命令行参数处理非常奇怪。为什么不直接使用普通的命令行参数呢?这使得问题变得微不足道:

    #!/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)
    
    如果您确实坚持将参数一起运行,然后用逗号分隔,那么可以使用以下方法。与您的原始版本一样,如果参数中的某个单词可以进行glob扩展,那么它将表现出意外的行为,因此我真的不推荐它:

    #!/usr/bin/bash
    IFS=, read -ra args <<<"$*"
    echo $(shuf -en1 "${args[@]}")
    
    #/usr/bin/bash
    如果coreutils中的IFS=,read-ra args正好做到这一点,但是使用多个命令参数而不是单个逗号分隔的参数

    shuf -n1 -e arg1 arg2 ...
    
    -n1
    选项表示只选择一个元素。
    -e
    选项表示元素将作为参数传递(而不是通过标准输入)

    然后,脚本只需在
    $*
    中用空格替换逗号即可。我们可以使用bash参数替换来实现这一点:

    #!/usr/bin/bash
    shuf -n1 -e ${*//,/ }
    
    这不适用于带有嵌入空格的元素。

    在coreutils中正好可以做到这一点,但是使用多个命令参数而不是单个逗号分隔的参数

    shuf -n1 -e arg1 arg2 ...
    
    -n1
    选项表示只选择一个元素。
    -e
    选项表示元素将作为参数传递(而不是通过标准输入)

    然后,脚本只需在
    $*
    中用空格替换逗号即可。我们可以使用bash参数替换来实现这一点:

    #!/usr/bin/bash
    shuf -n1 -e ${*//,/ }
    

    这对带有嵌入空格的元素不起作用。

    这不是很简单,只要在1和
    $#
    之间随机生成一个数字,然后简单地回显相应的参数就可以了吗?这取决于你拥有什么;你对“收集论据”的评论;请确保“用逗号分隔”不清楚,因为赋值不使用逗号,并且您没有显示如何调用命令

    我只是抄袭了问题中的随机数生成:它在我的Mac上正常工作,在连续运行时生成值42405691和1817261076

    n=$(( $(od -vAn -N4 -tu4 /dev/urandom) % $# + 1 ))
    eval echo "\${$n}"
    
    如果你真的下定决心,你甚至可以把它简化为一行:

    eval echo "\${$(( $(od -vAn -N4 -tu4 /dev/urandom) % $# + 1 ))}"
    
    使用
    eval
    是安全的,因为它不涉及用户输入。如果
    $#
    为0,脚本应检查是否至少提供了一个参数以防止被零除的错误。与以某种方式洗牌数据的解决方案相比,该代码的数据移动绝对最少

    如果它打包在脚本
    随机选择中
    ,那么我可以运行:

    $ 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位无符号值,如果它大于
    $#*(0xFFFFFF/$#*)
    ,您应该生成另一个随机数。

    这不是简单地在1和
    $#
    之间随机生成一个数字,然后简单地回显相应的参数吗?这取决于你拥有什么;你对“收集论据”的评论;请确保“用逗号分隔”不清楚,因为赋值不使用逗号,并且您没有显示如何调用命令

    我只是抄袭了问题中的随机数生成:它在我的Mac上正常工作,在连续运行时生成值42405691和1817261076

    n=$(( $(od -vAn -N4 -tu4 /dev/urandom) % $# + 1 ))
    eval echo "\${$n}"
    
    如果你真的下定决心,你甚至可以把它简化为一行:

    eval echo "\${$(( $(od -vAn -N4 -tu4 /dev/urandom) % $# + 1 ))}"
    
    使用
    eval
    是安全的,因为它不涉及用户输入。如果
    $#
    为0,脚本应检查是否至少提供了一个参数以防止被零除的错误。与以某种方式洗牌数据的解决方案相比,该代码的数据移动绝对最少

    如果它打包在脚本
    随机选择中
    ,那么我可以运行:

    $ 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/$#*)
    ,则应生成另一个随机数。

    ${words}始终为1。它应该是${#words[@]}@frangio:
    ${#words}
    并不总是1。它是
    $words
    的字符长度;如果
    words
    是一个数组,