Bash脚本编号生成器

时间:2013-10-13 23:26:36

标签: bash shell

我需要以特定格式生成随机数作为测试数据。例如,给定数字“n”我需要产生“n”个随机数并将它们写入文件中。该文件每行最多包含3个数字。这就是我所拥有的:

#!/bin/bash

m=$1
output=$2

for ((i=1; i<= m; i++)) do
    echo $((RANDOM % 29+2)) >> $output
done

输出数字为:

1
2
24
21
10
14

我想要的是:

1 2 24
21 10 14

感谢您的帮助!

6 个答案:

答案 0 :(得分:3)

将输出管道传输到一次读取3行的命令:

for ((i=1; i<= m; i++)) do
    echo $((RANDOM % 29+2))
done | sed -e '$!N;$!N;s/\n/ /g' >> $output

答案 1 :(得分:3)

Pure bash(写成函数而不是脚本文件)

randx3() {
  local d=$'  \n'
  local i
  for ((i=0;i<$(($1 - 1));++i)); do
    printf "%d%c" $((RANDOM%29 + 2)) "${d:$((i%3)):1}"
  done
  printf "%d\n" $((RANDOM%29 + 2))
}

请注意,它不带文件参数;而是输出到stdout,所以你会像这样使用它:

randx3 11 > /path/to/output

这种风格通常更灵活。

这是一个不太常见的问题,它允许您选择换行的频率:

randx() {
  local i
  local m=$1
  local c=${2:-3}
  for ((i=1;i<=m;++i)); do
    if ((i%c && i<m)); then
      printf "%d " $((RANDOM%29 + 2))
    else
      printf "%d\n" $((RANDOM%29 + 2))
    fi
  done
}

将其称为randx 11randx 11 7(第二个参数默认为3)。

答案 2 :(得分:1)

这是paste的目的:

$ for i in {0..10}; do echo $RANDOM; done | paste -d' ' - - -
14567 3240 16354
17457 25616 12772
3912 7490 12206
7342 10554 

另一种方法是在数组中构建值,然后使用printf。

m=$1
output=$2
vals=()
while (( m-- )); do
  vals+=( $((RANDOM % 29+2)) )
done
printf '%d %d %d\n' "${vals[@]}" > "$output"

答案 3 :(得分:1)

YAS :又一个解决方案

m=$1
output=$2
out=()
for ((i=1;i<=m;i++));do
    out+=($((RANDOM%29+2)))
    [ $((i%3)) -eq 0 ] && echo ${out[*]} >>$output && out=()
  done
[ "$out" ] && echo ${out[*]} >>$output

关于RANDOM%29

的评论

这种在2到30之间呈现随机的方式不是公平

$RANDOM给出032767之间的数字时,有:

for ((i=0;i<32768;i++)) ;do
    ((RL[$((i%29+2))]++))
  done
for ((i=0;i<32;i++));do
    printf "%3d %5d\n" $i ${RL[i]}
  done | column 

  0     0     7  1130        14  1130        21  1130        28  1130
  1     0     8  1130        15  1130        22  1130        29  1129
  2  1130     9  1130        16  1130        23  1130        30  1129
  3  1130    10  1130        17  1130        24  1130        31     0
  4  1130    11  1130        18  1130        25  1130
  5  1130    12  1130        19  1130        26  1130
  6  1130    13  1130        20  1130        27  1130

因此有1130个机会获得2到28之间的数字,但 1129获得29或30的机会。

为防止出现这种情况,您必须删除不需要的结果:

random2to30() {
    local _random=32
    while [ $_random -gt 28 ] ;do
        _random=$((RANDOM & 2#11111)) # return 5 bit random 0 to 31
      done
    printf -v $1 "%d" $((2+_random))  # Assign variable to prevent forks
}

证据:

tstr2to30() {
    unset $1
    local _random=32
    while [ $_random -gt 28 ] && read _random ;do
        _random=$((_random& 2#11111))
      done
    [ "$_random" ] && printf -v $1 "%d" $((2+_random))
}
unset RL
while tstr2to30 MyRandom && [ "$MyRandom" ] ;do
    ((RL[MyRandom]++))
  done < <(seq 0 32767)
for ((i=0;i<32;i++));do
    printf "%3d %5d\n" $i ${RL[i]}
  done | column 

提供:

  0     0    7  1024        14  1024        21  1024        28  1024
  1     0    8  1024        15  1024        22  1024        29  1024
  2  1024    9  1024        16  1024        23  1024        30  1024
  3  1024   10  1024        17  1024        24  1024        31     0
  4  1024   11  1024        18  1024        25  1024
  5  1024   12  1024        19  1024        26  1024
  6  1024   13  1024        20  1024        27  1024

所有值确实获得完全相同(1024)的机会。

最终可用脚本

所以脚本变成了(别忘了bash的shebang!):

#!/bin/bash

m=${1:-11}                  # default to 11 values
output=${2:-/dev/stdout}    # default to STDOUT
c=${3:-3}                   # default to 3 values by lines

random2to30() {
    local _random=32
    while [ $_random -gt 28 ] ;do
        _random=$((RANDOM & 2#11111)) # return 5 bit random 0 to 31
      done
    printf -v $1 "%d" $((2+_random))  # Assign variable to prevent forks
}

out=()
for ((i=1;i<=m;i++));do
    random2to30 MyRandom
    out+=($MyRandom)
    [ $((i%c)) -eq 0 ] && echo ${out[*]} >>"$output" && out=()
  done
[ "$out" ] && echo ${out[*]} >>"$output"

答案 4 :(得分:0)

此awk将在每第3行或空格后插入换行符:

for ((i=1; i<= m; i++)); do
    echo $((RANDOM % 29+2))
done | awk '{printf "%s%c", $1, (NR % 3) ? " " : "\n"}' >> $output

答案 5 :(得分:0)

另一种方法:

eval echo {1..$m} | xargs -n3 echo $((RANDOM % 29+2)) > $output