如何在Unix shell中将昨天的日期存入一个变量?

45

我有一个shell脚本,用于将当前日期存储在变量'dt'中,具体操作如下:

date "+%a %d/%m/%Y" | read dt
echo ${dt}

如何将昨天的日期存入变量中?

我想要做的就是使用grep从日志文件中提取所有昨天的行,因为日志中的每一行都包含“Mon 01/02/2010”格式的日期。

非常感谢!


1
如果需要的话,Perl是一个选择... - Chris
17个回答

77
dt=$(date --date yesterday "+%a %d/%m/%Y")
echo $dt

警告是:海报版本的Unix可能不支持“-yesterday”标志。 - James Anderson
“昨天” 的简短语法:-d yesterday。 - COil

53

在Linux上,你可以使用

date -d "-1 days" +"%a %d/%m/%Y"

3
这是所有其他答案中最好的答案,简短、甜美、易懂、方便、酷,并且它证明了那句话的故事:“授人以鱼不如授人以渔”。 - mtk
对于AIX用户而言,遗憾的是date命令不支持-d标志。 - Davy M
谢谢。有所帮助。 - Kanav Narula

17

您可以使用GNU日期命令如下所示:

获取过去的日期

要获取昨天和更早的日期,请使用字符串“day ago”:

date --date='yesterday'(昨天)

date --date='1 day ago'(一天前)

date --date='10 day ago'(10天前)

date --date='10 week ago'(10周前)

date --date='10 month ago'(10个月前)

date --date='10 year ago'(10年前)

获取未来的日期

要获取明天和后天的日期(明天+N),请使用单词“day”以获取未来的日期,如下所示:

date --date='tomorrow'(明天)

date --date='1 day'(一天后)

date --date='10 day'(10天后)

date --date='10 week'(10周后)

date --date='10 month'(10个月后)

date --date='10 year'(10年后)


14

如果您可以使用Perl(并且您的date没有像yesterday这样的好用功能),您可以使用以下代码:

pax> date
Thu Aug 18 19:29:49 XYZ 2010

pax> dt=$(perl -e 'use POSIX;print strftime "%d/%m/%Y%",localtime time-86400;')

pax> echo $dt
17/08/2010

1
@Chris:请注意,这会给你24小时前的日期,这与昨天的日期略有不同。如果您所在地区采用夏令时制度,在冬令时的第一天晚上23:00后,这将会给出错误的日期。 - Gilles 'SO- stop being evil'
@Gilles,这不是一个坏点子,因为我正在使用locattime。如果你担心它,你可以检查小时是否大于晚上6点,只需减去6个小时。这应该能解决问题。 - paxdiablo
好观点Gilles。我想念我的C# <哭泣>:DateTime.Now.AddDays(-1) - Chris
brew install coreutils 安装 GNU date 作为 gdate。可在 macOS 和 Linux 上使用。 - HappyFace

10

如果您使用的是 Mac、BSD 或其他没有 --date 选项的操作系统,您可以使用以下命令:

date -r `expr \`date +%s\` - 86400` '+%a %d/%m/%Y'

更新:或者也许...

date -r $((`date +%s` - 86400)) '+%a %d/%m/%Y'

2
使用 $() 而不是 \`` 会更方便。ksh 支持 $()` 吗? - bstpierre
2
+1 只是因为不假设每个 UNIX 问题都在 Linux 上。我们中的一些人也必须使用其他风格工作。 - paxdiablo
@paxdiablo:同意,但如果没有给出具体信息,我个人会认为GNU工具包是一个选项;HP-UXAIXSolaris*BSD之间的差异太大了,无法猜测其类型。 - Wolph
这个在一些奇怪的边缘情况下会失败吗?比如说有闰秒的时候? - Alok Singhal
1
$(( 用于算术扩展非常好,但这不是@bstpierre所说的。即使在其中,您也应该真正使用 $(...) 进行命令扩展:$(( $(date +%s) - 86400 )) - Mark Reed
显示剩余3条评论

7

我在Linux中有一个shell脚本,以下代码对我有效:

#!/bin/bash
yesterday=`TZ=EST+24 date +%Y%m%d` # Yesterday is a variable
mkdir $yesterday # creates a directory with  YYYYMMDD format

1
TZ 是时区,EST+24 表示美国东部标准时间的昨天日期(同样地,您可以使用 EST-24 来获取明天的日期)。+%Y%m%d 是 YYYYMMDD 的日期格式。 - jujuBee
2
这绝对是在AIX上运行的最简洁版本,适用于任何正在寻找此类答案的人。AIX不允许使用-r或-d标志,但实际上可以像这样操作时区!你让我开心了,我一直在尝试解决这个问题已经两个小时了,我想让一个日期显示为半年前,其他方法都不起作用。 - Davy M

5
请尝试以下方法:
dt=`case "$OSTYPE" in darwin*) date -v-1d "+%s"; ;; *) date -d "1 days ago" "+%s"; esac`
echo $dt

它可以在Linux和OSX上运行。


4

你至少有两个选项

  1. Use perl:

    perl -e '@T=localtime(time-86400);printf("%02d/%02d/%02d",$T[4]+1,$T[3],$T[5]+1900)'
    
  2. Install GNU date (it's in the sh_utils package if I remember correctly)

    date --date yesterday "+%a %d/%m/%Y" | read dt
    echo ${dt}
    
  3. Not sure if this works, but you might be able to use a negative timezone. If you use a timezone that's 24 hours before your current timezone than you can simply use date.


@Chris:我认为它不会是GNU兼容的“日期”命令,但由于您没有指定Unix变量,所以我只是猜测了一下;但在HP-UX系统中,您的选择有点受限,因为“日期”命令没有这些选项,所以使用Perl可能是最好的选择。 - Wolph
虽然这并不重要,但如果你接下来要对结果进行%100的话,你就不需要将年份加上1900了 :-) - paxdiablo
@paxdiablo:说得好,Perl 显然不是我的强项;)我会点赞你的答案。 - Wolph

3
这是一个ksh脚本,用于计算第一个参数的前一天日期,在Solaris 10上测试通过。
#!/bin/ksh
 sep=""
 today=$(date '+%Y%m%d')
 today=${1:-today}
 ty=`echo $today|cut -b1-4` # today year
 tm=`echo $today|cut -b5-6` # today month
 td=`echo $today|cut -b7-8` # today day
 yy=0 # yesterday year
 ym=0 # yesterday month
 yd=0 # yesterday day

 if [ td -gt 1 ];
 then
         # today is not first of month
         let yy=ty       # same year
         let ym=tm       # same month
         let yd=td-1     # previous day
 else
         # today is first of month
         if [ tm -gt 1 ];
         then
                 # today is not first of year
                 let yy=ty       # same year
                 let ym=tm-1     # previous month
                 if [ ym -eq 1 -o ym -eq 3 -o ym -eq 5 -o ym -eq 7 -o ym -eq 8 -o ym -     eq 10 -o ym -eq 12 ];
                 then
                         let yd=31
                 fi
                 if [ ym -eq 4 -o ym -eq 6 -o ym -eq 9 -o ym -eq 11 ];
                 then
                         let yd=30
                 fi
                 if [ ym -eq 2 ];
                 then
                         # shit... :)
                         if [ ty%4 -eq 0 ];
                         then
                                 if [ ty%100 -eq 0 ];
                                 then
                                         if [ ty%400 -eq 0 ];
                                         then
                                         #echo divisible by 4, by 100, by 400
                                                 leap=1 
                                         else
                                         #echo divisible by 4, by 100, not by 400
                                                 leap=0
                                         fi
                                 else
                                         #echo divisible by 4, not by 100
                                         leap=1 
                                 fi
                         else
                                 #echo not divisible by 4
                                 leap=0 # not divisible by four
                         fi
                         let yd=28+leap
                 fi
         else
                 # today is first of year
                 # yesterday was 31-12-yy
                 let yy=ty-1     # previous year
                 let ym=12
                 let yd=31
         fi
 fi
 printf "%4d${sep}%02d${sep}%02d\n" $yy $ym $yd

测试

bin$ for date in 20110902 20110901 20110812 20110801 20110301 20100301 20080301 21000301 20000301 20000101 ; do yesterday $date; done
20110901
20110831
20110811
20110731
20110228
20100228
20080229
21000228
20000229
19991231

2

虽然所有的回答都不错,但很遗憾对我都没用。所以我只能采用一些老派的方法。(因为我使用的是一个最基本的 Linux 操作系统)

$ date -d @$( echo $(( $(date +%s)-$((60*60*24)) )) )

您可以将此与日期的常规格式化结合使用。例如:
$ date -d @$( echo $(( $(date +%s)-$((60*60*24)) )) ) +%Y-%m-%d

解释: 以 Epoch 秒为单位输入日期(使用 -d 选项),从中减去一天的秒数。这将使日期精确地向前推移一天。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接