unix shell 获取第 n 个工作日的脚本
unix shell script to get nth business day
参考 this unix.com thread 上发布的获取当月第 N 个工作日的解决方案,我尝试使用以下代码获取当月的第 16 个工作日,但它不起作用。
currCal=`/usr/bin/cal`
BUSINESS_DAYS=`echo $($currCal|nawk 'NR>2 {print substr([=11=],4,14)}' |tr "\n" " ")`
执行时的错误是:
nawk: syntax error at source line 1 context is
NR>2 {print >>> substr(test. <<< sh,4,14)}
nawk: illegal statement at source line 1
我猜它使用 [=12=]
作为脚本名称,导致语法错误。请帮忙。
你上面的内容似乎有一些问题。
首先,我同意@John1024 的观点,为了获得您发布的 nawk 错误,您实际上必须 运行ning:
BUSINESS_DAYS=`echo $($currCal|nawk "NR>2 {print substr([=10=],4,14)}" |tr "\n" " ")`
用双引号将 nawk 脚本括起来。
此外,一旦您解决了 nawk 错误,您将 运行 遇到有关您如何使用 currCal
的问题。您将 cal
命令的实际输出放入 currCal
变量中,但随后将变量值(即 cal
的输出)用作 [=23= 之前的命令] 而不是 echo
将其放入管道或类似的东西中。
这带来了一个额外的问题,即为什么您在另一个子 shell(外部``s)中的子 shell 命令($()
部分)的结果上使用 echo
。
最后,您在上面显示的两行仅将当月的工作日列表获取到 BUSINESS_DAYS
变量中。他们没有 output/save 第 16 个这样的日子。
考虑到以上所有因素(并更改为始终使用 $()
子 shell 语法),您可能需要以下调用之一:
如果确实需要缓存当月日历,想拉多天:
currCal="$(/usr/bin/cal)"
BUSINESS_DAYS="$(echo "${currCal}" | \
nawk 'NR>2 {print substr([=11=],4,14)}' | \
tr "\n" " ")"
DAY=16
DAYTH_DAY="$(echo "${BUSINESS_DAYS}" | nawk -v "day=${DAY}" '{ print $day }')
如果这只是一个one-and-done:
DAY=16
DAYTH_DAY="$(/usr/bin/cal | \
nawk 'NR>2 {print substr([=12=],4,14)}' | \
tr "\n" " " | \
nawk -v "day=${DAY}" '{ print $day }')"
另外注意:如果完全在 awk(/nawk) 中完成,这里的处理可以简化,但我想坚持您已经选择的基本框架。
根据评论中的要求更新:
纯 POSIX awk 版本:
DAY=16
DAYTH="$(cal | awk -v "day=${DAY}" '
(NR < 3) { next ; }
/^.[0-9 ]/ { ="" ; }
/^ / || (NF == 7) { $NF="" ; }
{ hold=hold [=13=] ; }
END { split(hold,arr," ") ; print arr[day] ; }')"
是的,简化见仁见智,我相信有人可以使它更简洁。工作原理说明:
跳过校准输出的header:
(NR < 3) { next ; }
对于星期天的日期,trim那个星期天的日期:
/^.[0-9 ]/ { ="" ; }
对于周日(一个月的第一周)之后开始的周或整整七天的周,trim该周的周六日期:
/^ / || (NF == 7) { $NF="" ; }
一旦这些行只有工作日的日期,将它们柯里化成 hold
:
{ hold=hold [=17=] ; }
最后,在空格上拆分 hold
这样我们就可以抢到第 N 天了:
END { split(hold,arr," ") ; print arr[day] ; }')"
没有awk
,只有软件工具:
set -- $(cal -h | rev | cut --complement -b-5,20- | rev | tail -n +3) ; \
shift 15 ; echo
输出:
22
cal
的输出很难解析,因为:
- 这是对的。
- 它是 space 分隔的。
- 一个或两位数的日期表示两个或一个分隔 spaces.
- 本月第一天的前导数 space。
- 如果没有
-h
选项,解析将无法正常工作(关闭 'today' 突出显示)。
参考 this unix.com thread 上发布的获取当月第 N 个工作日的解决方案,我尝试使用以下代码获取当月的第 16 个工作日,但它不起作用。
currCal=`/usr/bin/cal`
BUSINESS_DAYS=`echo $($currCal|nawk 'NR>2 {print substr([=11=],4,14)}' |tr "\n" " ")`
执行时的错误是:
nawk: syntax error at source line 1 context is NR>2 {print >>> substr(test. <<< sh,4,14)} nawk: illegal statement at source line 1
我猜它使用 [=12=]
作为脚本名称,导致语法错误。请帮忙。
你上面的内容似乎有一些问题。
首先,我同意@John1024 的观点,为了获得您发布的 nawk 错误,您实际上必须 运行ning:
BUSINESS_DAYS=`echo $($currCal|nawk "NR>2 {print substr([=10=],4,14)}" |tr "\n" " ")`
用双引号将 nawk 脚本括起来。
此外,一旦您解决了 nawk 错误,您将 运行 遇到有关您如何使用 currCal
的问题。您将 cal
命令的实际输出放入 currCal
变量中,但随后将变量值(即 cal
的输出)用作 [=23= 之前的命令] 而不是 echo
将其放入管道或类似的东西中。
这带来了一个额外的问题,即为什么您在另一个子 shell(外部``s)中的子 shell 命令($()
部分)的结果上使用 echo
。
最后,您在上面显示的两行仅将当月的工作日列表获取到 BUSINESS_DAYS
变量中。他们没有 output/save 第 16 个这样的日子。
考虑到以上所有因素(并更改为始终使用 $()
子 shell 语法),您可能需要以下调用之一:
如果确实需要缓存当月日历,想拉多天:
currCal="$(/usr/bin/cal)"
BUSINESS_DAYS="$(echo "${currCal}" | \
nawk 'NR>2 {print substr([=11=],4,14)}' | \
tr "\n" " ")"
DAY=16
DAYTH_DAY="$(echo "${BUSINESS_DAYS}" | nawk -v "day=${DAY}" '{ print $day }')
如果这只是一个one-and-done:
DAY=16
DAYTH_DAY="$(/usr/bin/cal | \
nawk 'NR>2 {print substr([=12=],4,14)}' | \
tr "\n" " " | \
nawk -v "day=${DAY}" '{ print $day }')"
另外注意:如果完全在 awk(/nawk) 中完成,这里的处理可以简化,但我想坚持您已经选择的基本框架。
根据评论中的要求更新:
纯 POSIX awk 版本:
DAY=16
DAYTH="$(cal | awk -v "day=${DAY}" '
(NR < 3) { next ; }
/^.[0-9 ]/ { ="" ; }
/^ / || (NF == 7) { $NF="" ; }
{ hold=hold [=13=] ; }
END { split(hold,arr," ") ; print arr[day] ; }')"
是的,简化见仁见智,我相信有人可以使它更简洁。工作原理说明:
跳过校准输出的header:
(NR < 3) { next ; }
对于星期天的日期,trim那个星期天的日期:
/^.[0-9 ]/ { ="" ; }
对于周日(一个月的第一周)之后开始的周或整整七天的周,trim该周的周六日期:
/^ / || (NF == 7) { $NF="" ; }
一旦这些行只有工作日的日期,将它们柯里化成 hold
:
{ hold=hold [=17=] ; }
最后,在空格上拆分 hold
这样我们就可以抢到第 N 天了:
END { split(hold,arr," ") ; print arr[day] ; }')"
没有awk
,只有软件工具:
set -- $(cal -h | rev | cut --complement -b-5,20- | rev | tail -n +3) ; \
shift 15 ; echo
输出:
22
cal
的输出很难解析,因为:
- 这是对的。
- 它是 space 分隔的。
- 一个或两位数的日期表示两个或一个分隔 spaces.
- 本月第一天的前导数 space。
- 如果没有
-h
选项,解析将无法正常工作(关闭 'today' 突出显示)。