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 的输出很难解析,因为:

  1. 这是对的。
  2. 它是 space 分隔的。
  3. 一个或两位数的日期表示两个或一个分隔 spaces.
  4. 本月第一天的前导数 space。
  5. 如果没有 -h 选项,解析将无法正常工作(关闭 'today' 突出显示)。