2

需要帮助。我想将 csv 中的日期(这是一个字符串)列增加一天。例如(日期格式 yyyy-MM-dd)

Col1,Col2,Col3
ABC,001,1900-01-01
XYZ,002,2000-01-01

预期产出

Col1,Col2,Col3
ABC,001,1900-01-02
XYZ,002,2000-01-02
4

3 回答 3

3

有一个标准的 Unix 实用程序内置了从 1752 年 9 月 14 日到 9999 年 12 月 31 日的所有日期魔法:日历cal。我们不会重新发明轮子并进行混乱的日期计算,而是利用它的智能来发挥我们的优势。基本问题是:给定一个日期,是一个月的最后一天吗?如果没有,只需增加一天。如果是,则将天重置为 1 并增加月份(可能还有年份)。

但是, 的输出cal未指定,可能如下所示:

$ cal 2 1900
   February 1900
Su Mo Tu We Th Fr Sa
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28

我们需要的是天的列表,1 2 3 ... 28。我们可以通过跳过所有内容到“1”来做到这一点:

 set -- $(cal 2 1900)
 while test $1 != 1; do shift; done

现在 args 的数量为我们提供了 1900 年 2 月的天数:

 $ echo $#
 28

将它们放在一个脚本中:

#!/bin/sh

read -r header
printf "%s\n" "$header"

while IFS=,- read -r col1 col2 y m d; do
  case $m-$d in
    (12-31) y=$((y+1)) m=01 d=01;;
    (*)
      set -- $(cal $m $y)
      # Shift away the month and weekday names.
      while test $1 != 1; do shift; done
      # Is the day the last day of a month?
      if test ${d#0} -eq $#; then
        # Yes: increment m and reset d=01.
        m=$(printf %02d $((${m#0}+1)))
        d=01
      else
        # No: increment d.
        d=$(printf %02d $((${d#0}+1)))
      fi
    ;;
  esac
  printf "%s,%s,%s-%s-%s\n" "$col1" "$col2" $y $m $d
done

在此输入上运行它:

Col1,Col2,Col3
ABC,001,1900-01-01
ABC,001,1900-02-28
ABC,001,1900-12-31
XYZ,002,2000-01-01
XYZ,002,2000-02-28
XYZ,002,2000-02-29

产量

Col1,Col2,Col3
ABC,001,1900-01-02
ABC,001,1900-03-01
ABC,001,1901-01-01
XYZ,002,2000-01-02
XYZ,002,2000-02-29
XYZ,002,2000-03-01

我做了一个小假设:前两列不包含-逗号或转义逗号。如果他们这样做,IFS=,- read意志就会行动起来。

于 2013-05-31T12:37:17.020 回答
1

使用date命令,这可以在 awk 中完成:

awk 'BEGIN{FS=OFS=","}NR>1{("date -d\""$3" +1 day\" +%Y-%m-%d")|getline newdate; $3=newdate; print}' file.in
于 2013-05-31T14:55:47.947 回答
0

如果您可以从文件中提取日期,则可以使用:

d="1900-01-01"  # date from file
date --date '@'$(( $(date --date $d +"%s") + 86400 ))
于 2013-06-03T08:29:38.840 回答