Shell unix awk从日期月份字段减去整数字段
我有一个大约有10毫米记录的文件。这是我的dateSample src文件:Shell unix awk从日期月份字段减去整数字段,shell,date,unix,awk,Shell,Date,Unix,Awk,我有一个大约有10毫米记录的文件。这是我的dateSample src文件: 0000000566 2017/01/01 0 0000000055 2017/01/01 0 0000000109 2017/01/01 1 0000000940 2017/01/01 0 0000000566 2017/01/01 1 0000000055 2017/01/01 1 0000000109 2017/01/01 2 我基本上需要减去日期中月份的最后一个整数值,然后打印不带整数值的新值,因此: 000
0000000566 2017/01/01 0
0000000055 2017/01/01 0
0000000109 2017/01/01 1
0000000940 2017/01/01 0
0000000566 2017/01/01 1
0000000055 2017/01/01 1
0000000109 2017/01/01 2
我基本上需要减去日期中月份的最后一个整数值,然后打印不带整数值的新值,因此:
0000000566 2017/01/01
0000000055 2017/01/01
0000000109 2016/12/01
0000000940 2017/01/01
0000000566 2016/12/01
0000000055 2016/12/01
0000000109 2016/11/01
我在date(或macOS上的gdate)方面遇到了真正的问题,在过去几天里一直在徒劳地搜索。它要么以零作为前缀,然后删除m和d值:
awk '{ print (gdate -d $2 +"%Y/%m/%d") }' <$src
awk'{print(gdate-d$2+%Y/%m/%d”)}'由于您正在处理日期,因此最好在shell本身中执行此操作:
while read -r str date n; do
echo "$str $(date -d "$(date -d $date) -$n months" '+%Y/%m/%d')"
done < file
0000000566 2017/01/01
0000000055 2017/01/01
0000000109 2016/12/01
0000000940 2017/01/01
0000000566 2016/12/01
0000000055 2016/12/01
0000000109 2016/11/01
读取时-r str date n;做
echo“$str$(日期-d”$(日期-d$日期)-$n个月”+%Y/%m/%d')”
完成<文件
0000000566 2017/01/01
0000000055 2017/01/01
0000000109 2016/12/01
0000000940 2017/01/01
0000000566 2016/12/01
0000000055 2016/12/01
0000000109 2016/11/01
如果您的awk
支持mktime
和strftime
(这是GNU扩展),您可以这样做:
awk -F'[ /]' '{print $1 " " strftime("%Y/%m/%d", mktime($2" "($3-$5)" "$4" 0 0 0"))}' file
首先,我们将日期转换为Unix时间戳mktime
只接受“YYYY-MM-DD-HH-MM-SS”格式的日期,这就是为什么我们需要手动构造它。但是它会自动进行标准化,并且它会很高兴地将“2017-110 00”
转换为与“2016 11 100 00”
相同的时间戳
之后,我们只需要将时间戳转换为“y/m/d”格式并打印它
或者,您可以在不需要日期规范化的简单情况下“手工”进行日期运算——如果月份的日期总是,请尝试一种更简单的方法来解决此问题
awk 'BEGIN{
split("01,02,03,04,05,06,07,08,09,10,11,12", month,",")
}
{
split($2, array,"/");
if(array[2]<=$3){
array[2]=array[2]+12-$3;
array[1]=array[1]-1
}
else{
array[2]-$3
};
print $1,array[1]"/"array[2]"/"array[3]
}
' Input_file
awk'开始{
拆分(“01,02,03,04,05,06,07,08,09,10,11,12”,月“,”)
}
{
拆分($2,数组“/”);
如果(数组[2]不会很慢,因为您在每行调用外部date
(两次)?另外,您对date
的内部调用不应该是:$(date-d“$date”+%Y/%m/%d”)
?感谢@randomir它现在已经修复。您好……感谢上面的内容,但它在2017-05-01的日期不起作用。这里有一个调整版本:awk'{split($2,array,“/”);if($3>0){if(array[2]=“01”){array[1]=array[1]=array[2]+12-$3;if(array[2]<10){array[2]=“0”数组[2]}否则{array[2]=数组[2]-$3如果(数组[2]<10){array[2]=“0”数组[2]};}打印$1,数组[1]“/”数组[2]“/”数组[3]}“回复真棒……感谢您的详细解释。strftime-mktime组合非常好,运行速度非常快。还感谢“手动”版本的完整性。感谢您的帮助。干杯
while read -r str date n; do
echo "$str $(date -d "$(date -d $date) -$n months" '+%Y/%m/%d')"
done < file
0000000566 2017/01/01
0000000055 2017/01/01
0000000109 2016/12/01
0000000940 2017/01/01
0000000566 2016/12/01
0000000055 2016/12/01
0000000109 2016/11/01
awk -F'[ /]' '{print $1 " " strftime("%Y/%m/%d", mktime($2" "($3-$5)" "$4" 0 0 0"))}' file
#!/usr/bin/awk -f
BEGIN {
FS = "[ /]";
}
{
mm = $2 * 12 + ($3 - 1) - $5;
y = int(mm / 12);
m = mm % 12 + 1;
d = $4;
printf("%s %04d/%02d/%02d\n", $1, y, m, d);
}
$ ./script.awk file
0000000566 2017/01/01
0000000055 2017/01/01
0000000109 2016/12/01
0000000940 2017/01/01
0000000566 2016/12/01
0000000055 2016/12/01
0000000109 2016/11/01
awk 'BEGIN{
split("01,02,03,04,05,06,07,08,09,10,11,12", month,",")
}
{
split($2, array,"/");
if(array[2]<=$3){
array[2]=array[2]+12-$3;
array[1]=array[1]-1
}
else{
array[2]-$3
};
print $1,array[1]"/"array[2]"/"array[3]
}
' Input_file