如何将Shell参数传递给Perl脚本?

时间:2012-12-20 13:30:03

标签: perl shell unix strftime

我试图以某种格式找到日期,我之前用perl(strftime)完成了,但那次我提到了静态时间,这次我需要一个变量$ CURRENT_DAY。< / p>

下面是问题,当使用CURRENT_DAY和整数等同DAYHOUR=86400时,变量给出正确的时间,但是一旦我在语句中放入$CURRENT_DAY变量,日期不会减少。

$ DAYHOUR=86400
$ DAY=1
$ CURRENT_DAY=`echo $(($DAYHOUR*$DAY))`
$ DD=`perl -e 'use POSIX; print strftime "%d", localtime time - $CURRENT_DAY;'`
$ echo $DD
20
$ DAY=`echo $(($DAY+1))`
$ CURRENT_DAY=`echo $(($DAYHOUR*$DAY))`
$ DD=`perl -e 'use POSIX; print strftime "%d", localtime time - $CURRENT_DAY;'`
$ echo $DD
20
$ DAY=`echo $(($DAY+1))`
$ echo $DAY
3
$ CURRENT_DAY=`echo $(($DAYHOUR*$DAY))`
$ echo $CURRENT_DAY
259200
$ echo `perl -e 'use POSIX; print strftime "%d", localtime time - 259200;'`
17

4 个答案:

答案 0 :(得分:4)

您的主要问题是$CURRENT_DAY是Perl脚本变量。通过将Perl脚本用单引号括起来,shell的同名变量没有可见性。如果你启用了警告(例如-w),你会看到这个。

有几种方法可以解决您的问题。一种是使用双引号来封装Perl,从而允许shell在运行Perl之前首先扩展其变量的值:

CURRENT_DAY=3
perl -MPOSIX -wle "print strftime qq(%d),localtime time-(86400*$CURRENT_DAY);print $CURRENT_DAY" 
17

另一个是:

export CURRENT_DAY=3
perl -MPOSIX -wle 'print strftime qq(%d),localtime time-(86400*$ENV{CURRENT_DAY})' 

请注意,从昨天或明天计算的24小时内添加或减去将无法正确计算夏令时的变化。见this faq

答案 1 :(得分:3)

您可以在@ARGV中将它们作为参数传递:

$ dd_seconds_ago () { perl -MPOSIX -e 'print strftime q(%d), localtime(time - shift)' "$@"; }

$ DD=$(dd_seconds_ago 86400)

没有参数,在上面的上下文中,shift改变了@ARGV,这对于像这样的shell单行来说很方便

答案 2 :(得分:1)

与Perl一样,sh不会在单引号字符串中进行插值,因此Perl会看到$CURRENT_DAY而不是实际数字,并且您从未为该Perl变量分配任何内容。你可以切换到双引号字符串。

perl -MPOSIX -e"print strftime '%d', localtime time-$CURRENT_DAY;"

这很好,因为$CURRENT_DAY是一个数字,但如果你想传递一个任意字符串,你可以使用env var或一个参数。

export CURRENT_DAY
perl -MPOSIX -e'print strftime "%d", localtime time-$ENV{CURRENT_DAY};'

perl -MPOSIX -e'print strftime "%d", localtime time-$ARGV[0];' -- "$CURRENT_DAY"

请注意,您的代码有问题。每年有两个小时的代码会给出错误的答案,因为并非所有日子都有86400秒。有些人有82800,有些人有90000.(而且假设闰秒没有考虑因素。)Perl解决方案没有遇到这个问题:

perl -MDateTime -e'print
   DateTime->today(time_zone=>"local")
    ->subtract(days=>$ARGV[0])
     ->strftime("%d")' -- "$DAY"

或者您可以使用date

date -d "$DAY days ago" +%d

答案 3 :(得分:0)

我假设您想要在shell变量DAY中传递过去的天数,并且您希望在shell变量DD中传递答案

因此,如果它是月份的第20个且DAY为1,那么DD应该设置为19

您可以按如下方式修改Perl命令:

 DD=`perl -e 'use POSIX; print strftime "%d", localtime( time - ($ENV{DAY}* 86400))';

或者,您可以使用广泛可用的GNU date命令

 DD=`date -d "$DAY days ago" +%d`

使用date可能更好地处理闰日等问题