Unix Shell 程序来检测它是哪个半月。月份中的第几天 (dom) -le 16

0 shell-script

最终目标是设置一个 YYYYMMDD 变量,其中 DD 是两个变量之一(01 或 16)

我正在尝试创建一个变量,使其成为两个值之一。

这是我到目前为止所拥有的,但它不起作用:

DYA=date +%d 
DYB=IF [["$DYA" -ge 16]]; then 16
else 01
fi
YR=2020
MO=03

FD="$YR$MO$DY"
ECHO "$FD"
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 7

使用bash4.2 或更高版本:

#!/bin/bash

printf -v day '%(%e)T' -1

if [[ $day -lt 16 ]]; then
    # 1st half of the month
    day=01
else
    # 2nd half of the month
    day=16
fi

printf '%(%Y%m)T%s\n' -1 "$day"
Run Code Online (Sandbox Code Playgroud)

第一个printf将月份的当前日期作为十进制数字打印到变量中day。这些if语句将其限制为0116取决于其值。

最后printf打印当前的年和月,然后将01or16字符串添加到此末尾。

调用的-1参数printf使%(...)T格式字符串使用当前时间作为格式化的时间戳(如果您使用的是bash4.3 或更高版本,则第一次调用不是严格需要的,因为它是隐式的)。

更紧凑的版本bash

#!/bin/bash

printf -v day '%(%e)T' -1
printf '%(%Y%m)T%.2d\n' -1 "$(( (day < 16) ? 1 : 16 ))"
Run Code Online (Sandbox Code Playgroud)

在这里,我使用通用三元运算符 在算术扩展中执行测试?:1如果$day小于 16,则计算字符串,如果大于 16,则计算字符串16。然后将算术扩展的结果格式化为一个填充零的整数,并插入到当前年份和月份之后。


关于你的代码:

  • 请注意,和[[ ... ]]周围都需要空格(好吧,因为它是命令终止符,所以可以在没有空格的情况下立即出现)。[[]];
  • 如果要将 的输出date或任何命令放入变量中,请使用命令替换:day=$( date +%e )。这适用于您的if语句,如果它要输出一个值(它不是)。
  • Unix 命令区分大小写,因此ECHO应该是echo.
  • %d时间格式输出之间的零填充的整数0131。需要注意的是算术上下文(使用这样的值if语句)会解释值01通过对07作为八进制值,并会产生错误的0809(这些都是无效的八进制数)。这就是为什么我使用%e代替来获取不是零填充的整数,介于1和之间31

关于最后一点:我也可以使用

printf -v day '%(%d)T' -1
Run Code Online (Sandbox Code Playgroud)

01和之间获得零填充值31,但是我将需要使用

printf -v day '%(%d)T' -1
Run Code Online (Sandbox Code Playgroud)

强制外壳将字符串解释为十进制整数而不是八进制整数。


作为/bin/sh脚本(也适用bash于 4.2 之前的版本,例如使用bashmacOS上的默认shell):

if [[ 10#$day -ge 16 ]]; then
Run Code Online (Sandbox Code Playgroud)

标准shshell 没有 的%(...)T格式字符串bash,因此我们被迫使用date来进行日期字符串格式化。它还[ ... ]用于测试而不是[[ ... ]](并且变量需要在其中用双引号引起来)。

更紧凑的版本/bin/sh

#!/bin/sh

day=$( date +%e )

if [ "$day" -lt 16 ]; then
    # 1st half of the month
    day=01
else
    # 2nd half of the month
    day=16
fi

date +"%Y%m$day"
Run Code Online (Sandbox Code Playgroud)

这个更紧凑的版本来自于紧凑的bash变体。唯一的区别是date用于格式化当前的年和月。