如何在不使用 if else 或 switch 或 while 循环的情况下使用 bash 获取当前年度每个月的最后一天?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12381501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use bash to get the last day of each month for the current year without using if else or switch or while loop?
提问by Hyman
As we know that each year have the following max day in each month as follows:
正如我们所知,每年每个月都有以下最大天数,如下所示:
Jan - 31 days
Feb - 28 days / 29 days (leap year)
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
How to I get bash to return the value (last day of each month) for the current year without using if else
or switch
or while
loop?
如何在不使用if else
orswitch
或while
循环的情况下让 bash 返回当前年份的值(每个月的最后一天)?
回答by glenn Hymanman
my take:
我的看法:
for m in {1..12}; do
date -d "$m/1 + 1 month - 1 day" "+%b - %d days";
done
To explain: for the first iteration when m=1 the -d
argument is "1/1 + 1 month - 1 day" and "1/1" is interpreted as Jan 1st. So Jan 1 + 1 month - 1 day is Jan 31. Next iteration "2/1" is Feb 1st, add a month subtract a day to get Feb 28 or 29. And so on.
解释一下:对于第一次迭代,当 m=1 时,-d
参数是“1/1 + 1 个月 - 1 天”,“1/1”被解释为 1 月 1 日。所以 Jan 1 + 1 月 - 1 天是 1 月 31 日。下一次迭代“2/1”是 2 月 1 日,加上一个月减去一天得到 2 月 28 日或 29 日。依此类推。
回答by clyfish
cat <<EOF
Jan - 31 days
Feb - `date -d "yesterday 3/1" +"%d"` days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
EOF
回答by amdn
Assuming you allow "for", then the following in bash
假设您允许“for”,那么 bash 中的以下内容
for m in {1..12}; do
echo $(date -d $m/1/1 +%b) - $(date -d "$(($m%12+1))/1 - 1 days" +%d) days
done
produces this
产生这个
Jan - 31 days
Feb - 29 days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
Note: I removed the need for cal
注意:我删除了对 cal
For those that enjoy trivia:
对于那些喜欢琐事的人:
Number months from 1 to 12 and look at the binary representation in four
bits {b3,b2,b1,b0}. A month has 31 days if and only if b3 differs from b0.
All other months have 30 days except for February.
So with the exception of February this works:
因此,除了二月,这都有效:
for m in {1..12}; do
echo $(date -d $m/1/1 +%b) - $((30+($m>>3^$m&1))) days
done
Result:
结果:
Jan - 31 days
Feb - 30 days (wrong)
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
回答by crazyswissie
回答by Josiah DeWitt
returns the number of days in the month compensating for February changes in leap years without looping or using an if statement and only calls date once.
在不循环或不使用 if 语句且仅调用 date 一次的情况下,返回月份中补偿闰年二月变化的天数。
This code tests date to see if Feb 29th of the requested year is valid, if so then it updates the second character in the day offset string. The month argument selects the respective substring and adds the month difference to 28.
此代码测试日期以查看请求年份的 2 月 29 日是否有效,如果有效,则更新日期偏移字符串中的第二个字符。月份参数选择相应的子字符串并将月差添加到 28。
function daysin()
{
s="303232332323" # normal year
date -d "2/29/" > /dev/null 2>&1 && s="313232332323" # leap year
echo $[ ${s:$[-1]:1} + 28 ]
}
daysin #daysin [1-12] [YYYY]
回答by Walk
Try using this code
尝试使用此代码
date -d "-$(date +%d) days month" +%Y-%m-%d
回答by Steve
Contents of script.sh
:
内容script.sh
:
#!/bin/bash
begin="-$(date +'%-m') + 2"
end="10+$begin"
for ((i=$begin; i<=$end; i++)); do
echo $(date -d "$i month -$(date +%d) days" | awk '{ printf "%s - %s days", , }')
done
Results:
结果:
Jan - 31 days
Feb - 29 days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
回答by Valentin Heinitz
for m in $(seq 1 12); do cal $(date +"$m %Y") | grep -v "^$" |tail -1|grep -o "..$"; done
- iterate from 1 to 12 (for...)
- print calendar table for each month (cal...)
- remove empty lines from output (grep -v...)
- print last number in the table (tail...)
- 从 1 到 12 迭代(对于...)
- 打印每个月的日历表(cal...)
- 从输出中删除空行 (grep -v...)
- 打印表中的最后一个数字(尾部...)
There is no sense, to avoid using cal, because it is required by POSIX, so should be there
没有意义,避免使用cal,因为POSIX需要它,所以应该有
回答by atmosx
On a Mac which features BSD dateyou can just do:
在具有BSD 日期功能的 Mac 上,您可以执行以下操作:
for i in {2..12}; do date -v1d -v"$i"m -v-1d "+%d"; done
Quick Explanation
快速说明
-v
stands for adjust. We are adjusting the date to:
-v
代表调整。我们将日期调整为:
-v1d
stands for first day of the month
-v1d
代表一个月的第一天
-v"$i"m
defined the month e.g. (-v2m
for Feb)
-v"$i"m
定义月份,例如(-v2m
对于二月)
-v-1d
minus one day (so we're getting the last day of the previous month)
-v-1d
减去一天(所以我们得到上个月的最后一天)
"+%d"
print the day of the month
"+%d"
打印一个月中的哪一天
for i in {2..12}; do date -v1d -v"$i"m -v-1d "+%d"; done
31
28
31
30
31
30
31
31
30
31
30
You can add year of course. See examples in the manpage (link above).
您当然可以添加年份。请参阅联机帮助页中的示例(上面的链接)。
回答by Sharuzzaman Ahmat Raslan
A variation for the accepted answer to show the use of "yesterday"
已接受答案的变体,以显示“昨天”的使用
$ for m in {1..12}; do date -d "yesterday $m/1 + 1 month" "+%b - %d days"; done
Jan - 31 days
Feb - 28 days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
How it works?
这个怎么运作?
Show the date of yesterday for the date "month/1" after adding 1 month
添加 1 个月后,为日期“月/1”显示昨天的日期