我有以下格式的数据集
第一和第二字段表示研究开始和结束的date(M / D / YYYY)。
如何将数据扩展为所需的输出格式,并考虑使用AWK或BASH脚本的闰年?
非常感激你的帮助。
Linux / Unix bash基本脚本awk / sed
如何在单引号包围的awk语句中使用单引号?
Jupyter笔记本的bash_kernel可以安装在Windows 7操作系统中
如何显示在Linux中匹配正则expression式的所有行
input
7/2/2009 7/7/2009 2/28/1996 3/3/1996 12/30/2001 1/4/2002
期望的输出
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
想要replacelinux文件中的2个string之间的特定字
以不规则的间隔计算平均值而不考虑shell脚本中的缺失值?
开关/shell在awk中不起作用
如何使用正则expression式来查找2个文件以在行尾查找匹配
sed两种模式search,并在第二种模式发生后追加线
如果你有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) }
示范:
./daterange.awk inputfile
输出:
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
编辑:
上面的脚本对天的长度有一个天真的假设。 这是一个小问题,但在某些情况下可能会产生意想不到的结果。 至少有一个其他答案也有这个问题。 据推测,减去(或加入)天数的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
只用bash就可以很好地完成:
for i in `seq 1 5`; do; date -d "2014-02-01 $i days" +%Y-%m-%d; done;
或用管道:
seq 1 5 | xargs -I {} date -d "2014-02-01 {} days" +%Y-%m-%d
你可以在没有awk的情况下在shell中完成这个工作,假设你有GNU日期(这是date -d @nnn表单所需要的,也可能是在单个数字天和几个月内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
如果您处于夏令时的地区,那么如果请求日光节约时间,则可能会出现混乱现象。 使用-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
只要在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
我更喜欢ISO 8601格式日期 – 这里是使用它们的解决方案。 如果你愿意,你可以很容易地适应美国的格式。
AWK脚本
BEGIN { days[ 1] = 31; days[ 2] = 28; days[ 3] = 31; days[ 4] = 30; days[ 5] = 31; days[ 6] = 30; days[ 7] = 31; days[ 8] = 31; days[ 9] = 30; days[10] = 31; days[11] = 30; days[12] = 31; } function leap(y){ return ((y %4) == 0 && (y % 100 != 0 || y % 400 == 0)); } function last(m,l,d){ d = days[m] + (m == 2) * l; return d; } function prev_day(date,y,m,d){ y = substr(date,1,4) m = substr(date,6,2) d = substr(date,9,2) #print d "/" m "/" y if (d+0 == 1 && m+0 == 1){ d = 31; m = 12; y--; } else if (d+0 == 1){ m--; d = last(m,leap(y)); } else d-- return sprintf("%04d-%02d-%02d",d); } { d1 = $1; d2 = $2; print d2; while (d2 != d1){ d2 = prev_day(d2); print d2; } }
数据
2009-07-02 2009-07-07 1996-02-28 1996-03-03 2001-12-30 2002-01-04
结果
执行的命令:
awk -f dates.awk dates.txt
输出:
2009-07-07 2009-07-06 2009-07-05 2009-07-04 2009-07-03 2009-07-02 1996-03-03 1996-03-02 1996-03-01 1996-02-29 1996-02-28 2002-01-04 2002-01-03 2002-01-02 2002-01-01 2001-12-31 2001-12-30
另一种选择是使用dateutils中的dateseq( http://www.fresse.org/dateutils/#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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。