3

我正在制作一个备份脚本,我需要在其中找到每个月的最后一个星期六。

我尝试了不同的方法来寻找这一天本身,这本身就非常有效。

问题是,当我尝试将它们放入我的脚本时,我总是得到错误代码 ./test.sh: line 13: [: 29: integer expression expected

这是我的代码:

#!/bin/bash

LASTSAT=$(ncal | grep Sa | awk '{print$(NF-0)}')
SATURDAY="6"

DAY=$(date +"%u")
DATE=$(date +"%d")

echo "$DAY"
echo "$DATE"
echo "$LASTSAT"

if [ $DATE -eq $LASTSAT  ]
then
 echo "sista lördagen..."
fi

我得到了将 if 语句更改为[ "$DATE" = "$LASTSAT" ] 删除错误本身的提示,但脚本会以某种方式不等于 27 到 27(以本月为例)。

我还尝试了另一种方法来查找最后一个星期六LASTSAT=$(cal|awk '{if(NF==7){SAT=$7}};END{print SAT}'),但如果我使用 -eq 并且使用 " with = 不等于 27 到 27,它会返回完全相同的错误。

我很困惑,没有想法,我在互联网上搜索并复制了其他人使用的确切线路,但结果都是一样的。

我究竟做错了什么?

4

8 回答 8

3

在测试期间,我更改了目标日期和一些变量名称,但以下脚本适用于该月的倒数第二个星期日。与您的脚本相关的关键更改是将-h开关添加到ncal,以关闭当天的突出显示。打印字段时突出显示字符显然会出现awk,但在执行 s 时不可见echo。请注意,您可以通过匹配删除grepafter 。ncalawk

#!/bin/bash

DoDay=$(ncal -h |awk '/Su/ {print $(NF-1)}')
Datum=$(date +%d)
echo $Datum Datum
echo $DoDay DoDay

if [[ $Datum == $DoDay ]]
then
    echo "sista lördagen..."
else
    echo "doh"
fi
于 2012-10-22T00:38:54.047 回答
3

您可以使用该命令轻松获取该月的最后一个星期六,该命令以格式date输出数据。strftime()但是date' 的语法将取决于您的操作系统。

在 FreeBSD 或 OSX中,有一个-v选项可以“调整”日期,让您有很多控制权:

[ghoti@pc ~]$ date -v+1m -v1d -v6w '+%a %d %b %Y'
Sat 03 Nov 2012
[ghoti@pc ~]$ date -v+1m -v1d -v6w -v-1w '+%a %d %b %Y'
Sat 27 Oct 2012

这里的想法是我们将向前移动 1 个月 ( +1m),回到本月的第一天 ( 1d),然后移动到一周的第 6 天,即星期六 ( 6w)。出于演示目的,第一行显示下个月的第一个星期六,第二行显示一周前( -v-1w) 的日期。

或者,如果您想在 bash 脚本中添加一些数学运算,您可以执行以下操作:

#!/usr/local/bin/bash

# Get day-of-the-week for the first-of-the-month:    
firstofmonth=$(date -j -v+1m -v1d '+%u')
     #                   ^
     #                   +  This is the relative month to current.

# Subtract this from 7 to find the date of the month
firstsaturday=$((7 - $firstofmonth))

# 7 days before that will be the last Saturday of the previous month
lastsaturday=$(date -j -v+1m -v${firstsaturday}d -v-7d '+%Y-%m-%d')

使用该-v选项,1 是一月,2 是二月,等等。或者它可以是相对的,正如我在这里展示的那样,下个月 +1,上个月 -1,等等。


在 Linux中, date 使用-d解释日期文本描述的选项。所以:

#!/bin/bash

firstofmonth=$(date -d '+1 months' '+%Y%m01')
firstsaturday=$(date -d "$firstofmonth" '+%Y-%m')-$(( 7 - $(date -d "$firstofmonth" '+%u') ))
lastsaturday=$(date -d "$firstsaturday -7 days" '+%d')

请注意,如果您使用的是 cron,则可以简化此操作。您知道最后一个星期六将在该月的最后 7 天之内,因此我们可以首先使用 cron 将事情限制在星期六,然后在脚本中检查该月的最后一个。这将在每个星期六运行该脚本,但它不会执行任何操作,除非它应该执行。例如,cron 选项卡是

#  ↙ "0 0"=midnight
0 0 * * 0 /path/to/script.sh
#        ↖ 0=Sunday

script.sh开始:

#!/bin/bash

if [[ $(date '+%d' -lt $(date -d "$(date -d '+1 month' '+%Y%m01') -7 days" '+%d') ]]; then
  exit
fi

您也可以将此测试放在 crontab 中,尽管它看起来有点难看,因为您需要转义百分号:

0 0 * * 0 \
  test $(date '+\%d') -ge $(date -d "$(date -d '+1 month' '+\%Y\%m01') -7 days" '+\%d') \
    && /path/to/command
于 2012-10-22T11:20:36.660 回答
2

这是使用以下方式打印每个月最后一个星期六的一种方法date

for i in {1..12}; do
    for j in {1..7}; do
        date=$(date -d "$i/1 + 1 month - $j day" +"%w %F")
        # day of week (1..7); 1 is Monday
        if [ ${date:0:1} -eq 6 ]; then
            echo ${date:2}
        fi
    done
done

结果:

2012-01-28
2012-02-25
2012-03-31
2012-04-28
2012-05-26
2012-06-30
2012-07-28
2012-08-25
2012-09-29
2012-10-27
2012-11-24
2012-12-29

如果您只想查找当月的最后一个星期六,请尝试:

for j in {1..7}; do
    month=$(date +"%m")
    date=$(date -d "$month/1 + 1 month - $j day" +"%w %F")
    # day of week (1..7); 1 is Monday
    if [ ${date:0:1} -eq 6 ]; then
        echo ${date:2}
    fi
done

结果:

2012-10-27

请注意,您可以通过更改%F为必须提供的任何格式date来更改上述脚本中这些结果的输出格式。见man date

于 2012-10-22T00:58:38.350 回答
1

这个怎么样:

last_saturday () 
{ 
    local Format;
    if [[ $1 =~ ^\+.* ]]; then
        Format=$1;
        shift;
    fi;
    local FirstOfNext="${1:-$(date +%B)} 1 $2 + 1 month";
    date $Format -d "$FirstOfNext - 1 day - 
                     $(($(date +%u -d "$FirstOfNext") % 7)) day"
}

例如:

$ last_saturday
Sat Oct 27 00:00:00 PET 2012
$ last_saturday November
Sat Nov 24 00:00:00 PET 2012
$ last_saturday June
Sat Jun 23 00:00:00 PET 2012
$ last_saturday June 2013
Sat Jun 29 00:00:00 PET 2013
$ last_saturday +%Y-%m-%d June 2013
2013-06-29
于 2012-10-22T03:30:32.117 回答
0

该脚本在我的系统(Ubuntu - Bash $)上运行良好。如果那天不是最后一个星期六,我刚刚修改了脚本以打印“!sista lördagen ...”,这是输出:
$sh abc.sh
7
21
27
!sista lordagen ...

于 2012-10-22T00:09:50.383 回答
0
#!/bin/bash
set -e

if [ "$#" -ne 2 ]; then
    echo "Usage: weekDayOfMonth.sh [weekOfMonth 1..4] [DayOfWeek where Sun=1]"
    exit 2;
fi

weekOfMonth=$1
dayOfWeek=$2 #starts with Sun(=1)

echo "weekOfMonth: $weekOfMonth";
echo "dayOfWeek: $dayOfWeek";

# cal starts with Sun, 3rd column is for Tue, 2nd row is 2nd Tue of month:
# Sun=1, dayIdx=0
# Mon=2, dayIdx=3
# Tue=3, dayIdx=6
# Wed=4, dayIdx=9
dayIdx=$(((dayOfWeek-1)*3))
expectedDayOfMonth=$(cal -s | sed "s/^.\{$dayIdx\}\(.\{3\}\).*$/\1/" | sed 's/^[ ]//g' | grep -o '[0-9]*' | head -$weekOfMonth | tail -1)
todaysDay=$(date +%d | sed 's/^0*//')

echo "expectedDayOfMonth: $expectedDayOfMonth";
echo "todaysDay: $todaysDay";

if [ ${expectedDayOfMonth} -ne ${todaysDay} ]; then
       echo "Today is NOT requested day of month, exiting with error code.";    
       exit 1;
fi
于 2015-05-21T14:00:33.953 回答
0

这是解决方案

if  [[ $(date +"%a") = "Sat" ]] && [[$(date -d "+7 days" +%m) != $(date +%m)]]
then
  echo "Last saturday of month"
fi
于 2021-01-21T12:41:44.630 回答
-1

这个怎么样:

if [ `date +%u` = 7 ] && [ `date +%m` != `date -d +week +%m` ]; then
  echo "sista lördagen..."
fi

...或简单地通过 crontab:

0 0 * * 0 [ `date +\%m` != `date -d +week +\%m` ] && /path/to/backup.sh
于 2018-07-27T15:32:42.147 回答