给定年份间隔,如何生成一系列随机日期?

Ray*_*d83 14 sed awk date random gawk

这里需要的是在给定年份范围(1987 年到 2017 年)的情况下生成六个日期的命令。例如:

12/10/1987
30/04/1998
22/02/2014
17/08/2017
19/07/2011
14/05/2004
Run Code Online (Sandbox Code Playgroud)

如何它可以做,用sed,gawk等?

Fre*_*ddy 21

与date,shuf和xargs:

将开始和结束日期转换为“自 1970-01-01 00:00:00 UTC 以来的秒数”并用于shuf打印此范围内的六个随机值。将此结果通过管道传输到xargs并将值转换为所需的日期格式。

编辑:如果您希望 2017 年的日期包含在输出中,您必须2017-12-31 23:59:59在结束日期添加一年 -1s ( )。shuf -i生成随机数,包括开始和结束。

shuf -n6 -i$(date -d '1987-01-01' '+%s')-$(date -d '2017-01-01' '+%s')\
 | xargs -I{} date -d '@{}' '+%d/%m/%Y'
Run Code Online (Sandbox Code Playgroud)

示例输出:

07/12/1988
22/04/2012
24/09/2012
27/08/2000
19/01/2008
21/10/1994
Run Code Online (Sandbox Code Playgroud)


A.B*_*A.B 10

您可以将问题转化为在代表第一个可能日期的数字和代表最后一个可能日期的数字(实际上是最后一个可能日期之后的数字)之间以 unix epoch 格式生成一个随机数。其他一切都由标准日期转换处理。gawk具有比bash(浮点数与 15 位整数)更好的随机数分辨率,所以我将使用gawk. 请注意,rand()结果 N 是一个浮点数,使得 0 <= N < 1,这就是为什么上限增加到以下的原因,这是一个无法滚动的限制。结果数量有一个可选的第三个参数。

#!/usr/bin/gawk -f
BEGIN {
    first=mktime(ARGV[1] " 01 01 00 00 00")
    last=mktime(ARGV[2]+1 " 01 01 00 00 00")
    if (ARGC == 4) { num=ARGV[3] } else { num=1 }
    ARGC=1
    range=last-first
    srand(sprintf("%d%06d", systime(), PROCINFO["pid"]))
    for (i=1; i <= num; i++) {
        print strftime("%d/%m/%Y", range*rand()+first)
    }
}   
Run Code Online (Sandbox Code Playgroud)

例如:

./randomdate.gawk 1987 2017 6
26/04/1992
28/04/2010
21/04/2005
17/02/2010
06/10/2016
04/04/1998
Run Code Online (Sandbox Code Playgroud)


gle*_*man 10

珀尔:

perl -MTime::Piece -sE '
    my $t1 = Time::Piece->strptime("$y1-01-01 00:00:00", "%Y-%m-%d %H:%M:%S");
    my $t2 = Time::Piece->strptime("$y2-12-31 23:59:59", "%Y-%m-%d %H:%M:%S");
    do {
        my $time = $t1 + int(rand() * ($t2 - $t1));
        say $time->dmy;
    } for 1..6;
' -- -y1=1987 -y2=2017
Run Code Online (Sandbox Code Playgroud)

示例输出:

10-01-1989
30-04-1995
10-12-1998
02-01-2016
04-06-2006
11-04-1987
Run Code Online (Sandbox Code Playgroud)


Jef*_*ler 9

这是一种方法,主要是在 awk 中:

#!/bin/sh

[ "$end" -ge "$start" ] || exit 1

awk -v start=$1 -v end=$2 '
  BEGIN {
    srand();
    for(i=1; i <= 6; i++)
      printf "%02d/%02d/%d\n", 1 + rand() * 28, 1 + rand() * 12, start + rand() * (end-start);
  }
' < /dev/null
Run Code Online (Sandbox Code Playgroud)

shell 脚本接受两个参数并将它们作为变量传递给 awk,awk 不读取输入并完成BEGIN块中的所有工作。

在为随机数生成器播种后,它会在一条printf语句上循环 6 次。该打印语句通过生成一个介于 1 到 28 之间的随机数(对于 2 月是安全的)、1 到 12 之间的月份以及给定的开始和结束年份之间的随机数来选择范围内可能日期的子集。它是随机的,但不是完全覆盖——它永远不会在有它们的月份打印第 29-31 天。

另一种方式,使用 GNU date 和 bash 功能:

#!/bin/bash

start=$1
end=$2

[[ "$start" -le "$end" ]] || exit 1

startsec=$(date -d "1/1/$start" +%s)
for((i=1; i<=6; i++))
do
  r=$((RANDOM % (1 + end - start)*365*24*60*60))
  date -d @$((startsec + r)) +%d/%m/%Y
done
Run Code Online (Sandbox Code Playgroud)

它的工作原理是计算开始日期的 1 月 1 日以来的秒数,然后对于每个循环,它会提供一个随机的偏移秒数来添加;随机数仅限于跨越给定范围的秒数。GNU 日期然后将该日期处理为所需的格式。


ica*_*rus 5

如果年数的差异小于大约 90,您可以使用$RANDOMbash 中的变量为您提供天数的偏移量,并使用该date命令的有限能力进行计算。

#!/bin/bash
s=$(date +%s -d "1/1/$1")          # start in seconds since 1 Jan 1970
e=$(date +%s -d "1/1/$(($2+1))")   # start of end year +1 in seconds
days=$(((e-s)/(24*3600)))          # number of days from start to end
factor=$((32767/$days))            # RANDOM is 0 to 32767. See how many
toobig=$(($factor*$days))          # exact multiples of days.
                                   # if RANDOM is too large, draw again
for((i=0;i<${3:-1};i++))           # produce $3 random dates
do
    r=$RANDOM                      # find a random number < toobig
    while (( r >= toobig ))        # if toobig, then loop.
    do r=$RANDOM
    done
    offset=$(($r/$factor))         # get (0,days) from (0,factor*days)
    # output horrible day/month/year for N days past start date
    date -d "$offset days 1/1/$1" +%d/%m/%Y
done
Run Code Online (Sandbox Code Playgroud)

选择随机数的内循环尝试纠正偏差。如果随机数源可以为您提供 0、1、2、3、4、5、6、7、8 或 9,并且您想要一个介于 0 和 3 之间的随机数,那么如果您从源中获得 0 或 1你报告0,如果你得到2或3,那么你报告1,如果你得到4或5你报告2,如果你得到6或7你报告3,如果你得到8或9你忽略来自来源的这个数字.