4

我需要生成特定格式的随机数作为测试数据。例如,给定一个数字“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

谢谢您的帮助!

4

6 回答 6

3

纯 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))
}

请注意,它不需要文件参数;而是输出到标准输出,所以你可以像这样使用它:

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)。

于 2013-10-14T02:02:29.673 回答
3

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

for ((i=1; i<= m; i++)) do
    echo $((RANDOM % 29+2))
done | sed -e '$!N;$!N;s/\n/ /g' >> $output
于 2013-10-13T23:28:47.500 回答
1

最短!!!

我需要产生“n”个随机数并将它们写入一个文件。该文件必须每行最多包含 3 个数字。

pr -t -3 -s\  <(for ((n=6;n--;)){ echo $((RANDOM % 29+2));}) >file

然后

cat file
11 29 27
14 21 22

YAS:又一个解决方案

作为脚本:

#!/bin/bash

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

用法:

script <quantity of random> <filename>

关于重要的评论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=32769
    while (( $_random>=32741 )) ;do
        _random=$RANDOM;
    done;
    printf -v $1 "%d" $((2+_random%29))
}

证据:

tstr2to30() {
    unset $1
    local _random=32769
    while (( $_random>=32741 )); do
        read _random || break
    done
    [ "$_random" ] && printf -v $1 "%d" $((2 +_random % 29 ))
}
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  1129        14  1129        21  1129        28  1129
  1     0     8  1129        15  1129        22  1129        29  1129
  2  1129     9  1129        16  1129        23  1129        30  1129
  3  1129    10  1129        17  1129        24  1129        31     0
  4  1129    11  1129        18  1129        25  1129
  5  1129    12  1129        19  1129        26  1129
  6  1129    13  1129        20  1129        27  1129

所有价值都获得完全相同的(1129)机会!

最终可用脚本

所以脚本可以变成(不要忘记 bash 的 shebang!):

#!/bin/bash

n=${1:-11}                  # default to 11 values
c=${2:-3}                   # default to 3  values by lines
minval=${3:-2}              # default to 2  random min
maxval=${4:-30}             # defailt to 30 random max
file=${5:-/dev/stdout}      # default to STDOUT

rnum=$(( maxval - minval + 1 ))
rmax=$(( ( 32768 / rnum ) * rnum ))
randomGen() {
    local _random=33000
    while [ $_random -ge $rmax ] ;do
        _random=$RANDOM
      done
    printf -v $1 "%d" $(( minval +_random % rnum ))
}

out=()
for ((i=1;i<=n;i++));do
    randomGen MyRandom
    out+=($MyRandom)
    [ $((i%c)) -eq 0 ] && echo ${out[*]} >>"$file" && out=()
  done
[ "$out" ] && echo ${out[*]} >>"$file"
于 2013-10-14T08:50:06.547 回答
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"
于 2013-10-14T02:19:22.690 回答
0

另一种方法:

eval echo {1..$m} | xargs -n3 echo $((RANDOM % 29+2)) > $output
于 2013-10-14T16:30:57.570 回答
0

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

for ((i=1; i<= m; i++)); do
    echo $((RANDOM % 29+2))
done | awk '{printf "%s%c", $1, (NR % 3) ? " " : "\n"}' >> $output
于 2013-10-14T00:03:39.570 回答