如何使用AWK BASH脚本生成给定开始和结束日期的日期序列?

Ton*_*ony 20 unix bash awk

我有一个具有以下格式的数据集

第一和第二个字段表示研究开始和结束的日期(M/D/YYYY).

考虑到使用AWK或BASH脚本的闰年,如何将数据扩展为所需的输出格式?

非常感激您的帮忙.

输入

  7/2/2009   7/7/2009
  2/28/1996  3/3/1996
  12/30/2001 1/4/2002
Run Code Online (Sandbox Code Playgroud)

期望的输出

  7/7/2009
  7/6/2009
  7/5/2009
  7/4/2009
  7/3/2009
  7/2/2009
  3/3/1996
  3/2/1996
  3/1/1996
  2/29/1996
  2/28/1996
  1/4/2002
  1/3/2002
  1/2/2002
  1/1/2002
  12/31/2001
  12/30/2001
Run Code Online (Sandbox Code Playgroud)

Boh*_*dan 58

单独使用bash可以很好地完成它:

for i in `seq 1 5`;
do
  date -d "2017-12-01 $i days" +%Y-%m-%d;
done;
Run Code Online (Sandbox Code Playgroud)

或用管道:

seq 1 5 | xargs -I {} date -d "2017-12-01 {} days" +%Y-%m-%d
Run Code Online (Sandbox Code Playgroud)

  • `seq`和`date -d`都是GNUisms.在*BSD(包括Mac OSX)上,您可能需要`jot`和`date -j`.为了便于携带,我可能会跳到Awk或Perl. (3认同)

Pau*_*ce. 13

如果你有gawk:

#!/usr/bin/gawk -f
{
    split($1,s,"/")
    split($2,e,"/")
    st=mktime(s[3] " " s[1] " " s[2] " 0 0 0")
    et=mktime(e[3] " " e[1] " " e[2] " 0 0 0")
    for (i=et;i>=st;i-=60*60*24) print strftime("%m/%d/%Y",i)
}
Run Code Online (Sandbox Code Playgroud)

示范:

./daterange.awk inputfile
Run Code Online (Sandbox Code Playgroud)

输出:

07/07/2009
07/06/2009
07/05/2009
07/04/2009
07/03/2009
07/02/2009
03/03/1996
03/02/1996
03/01/1996
02/29/1996
02/28/1996
01/04/2002
01/03/2002
01/02/2002
01/01/2002
12/31/2001
12/30/2001
Run Code Online (Sandbox Code Playgroud)

编辑:

上面的脚本遭受了关于天数的天真假设.这是次要的,但在某些情况下会产生意想不到的结果.这里至少有一个其他答案也有这个问题.据推测,date减去(或添加)若干天的命令没有这个问题.

有些答案要求您提前知道天数.

这是另一种希望解决这些问题的方法:

while read -r d1 d2
do
    t1=$(date -d "$d1 12:00 PM" +%s)
    t2=$(date -d "$d2 12:00 PM" +%s)
    if ((t2 > t1)) # swap times/dates if needed
    then
        temp_t=$t1; temp_d=$d1
        t1=$t2;     d1=$d2
        t2=$temp_t; d2=$temp_d
    fi
    t3=$t1
    days=0
    while ((t3 > t2))
    do
        read -r -u 3 d3 t3 3<<< "$(date -d "$d1 12:00 PM - $days days" '+%m/%d/%Y %s')"
        ((++days))
        echo "$d3"
    done
done < inputfile
Run Code Online (Sandbox Code Playgroud)


cam*_*amh 10

你可以在没有awk的shell中执行此操作,假设你有GNU日期(date -d @nnn表单需要这个日期,并且可能在单个数字日和月份中去除前导零):

while read start end ; do
    for d in $(seq $(date +%s -d $end) -86400 $(date +%s -d $start)) ; do
        date +%-m/%-d/%Y -d @$d
    done
done
Run Code Online (Sandbox Code Playgroud)

如果您所在的区域设置可以进行夏令时,那么如果要求在其间发生夏令时切换的日期序列,则可能会混乱.使用-u强制为UTC,每天严格遵守86400秒.像这样:

while read start end ; do
    for d in $(seq $(date -u +%s -d $end) -86400 $(date -u +%s -d $start)) ; do
        date -u +%-m/%-d/%Y -d @$d
    done
done
Run Code Online (Sandbox Code Playgroud)

只需在stdin上输入你的输入.

您的数据输出是:

7/7/2009
7/6/2009
7/5/2009
7/4/2009
7/3/2009
7/2/2009
3/3/1996
3/2/1996
3/1/1996
2/29/1996
2/28/1996
1/4/2002
1/3/2002
1/2/2002
1/1/2002
12/31/2001
12/30/2001
Run Code Online (Sandbox Code Playgroud)


nis*_*ama 5

另一种选择是使用 dateutils ( http://www.fresse.org/dateutils/#dateseq ) 中的dateseq。-i更改输入格式并-f更改输出格式。-1当第一个日期晚于第二个日期时,必须指定为增量。

$ dateseq -i %m/%d/%Y -f %m/%d/%Y 7/7/2009 -1 7/2/2009
07/07/2009
07/06/2009
07/05/2009
07/04/2009
07/03/2009
07/02/2009
$ dateseq 2017-04-01 2017-04-05
2017-04-01
2017-04-02
2017-04-03
2017-04-04
2017-04-05
Run Code Online (Sandbox Code Playgroud)