我正在编写一个 bash 脚本,它接受与 crontab 相同的调度值(星期几、月份等)。
到目前为止,我的脚本能够接受每个值的星号(
*
),或特定值的整数。但是,我的脚本还需要支持范围 (-
)、列表 (,
) 和步长值 (/
),如此处所述。
这是我的使用说明:
function print_usage() {
echo "Usage: `basename $0` -a APPLICATION [-D DAY_OF_WEEK] [-M MONTH] [-d DAY_OF_MONTH] [-H HOUR] [-m MINUTE] [-u]"
echo "Options:"
echo " -a APPLICATION EMR application (application:container)"
echo " -D DAY_OF_WEEK day of the week (0 - 7) (Sunday=0 or 7)"
echo " -M MONTH month (1 - 12)"
echo " -d DAY_OF_MONTH day of the month (1 - 31)"
echo " -H HOUR hour (0 - 23)"
echo " -m MINUTE minute (0 - 59)"
echo " -u uninstall the CRON job(s) for the application"
exit 0
}
这些是我当前的验证:
if [[ ! $DAY_OF_WEEK =~ ^(0?[0-7]|\*)$ ]]; then
echo "ERROR: DAY_OF_WEEK parameter must be a positive integer (0 - 7) (Sunday=0 or 7) or an asterisk"
exit 1
fi
if [[ ! $MONTH =~ ^((0?[1-9]|1[0-2])|\*)$ ]]; then
echo "ERROR: MONTH parameter must be a positive integer (1 - 12) or an asterisk"
exit 1
fi
if [[ ! $DAY_OF_MONTH =~ ^((0?[1-9]|[1-2][0-9]|3[0-1])|\*)$ ]]; then
echo "ERROR: DAY_OF_MONTH parameter must be a positive integer (1 - 31) or an asterisk"
exit 1
fi
if [[ ! $HOUR =~ ^((0?[0-9]|1[0-9]|2[0-3])|\*)$ ]]; then
echo "ERROR: HOUR parameter must be a positive integer (0 - 23) or an asterisk"
exit 1
fi
if [[ ! $MINUTE =~ ^((0?[0-9]|[1-5][0-9])|\*)$ ]]; then
echo "ERROR: MINUTE parameter must be a positive integer (0 - 59) or an asterisk"
exit 1
fi
我不太确定如何开始支持调度参数的范围、列表和步长值。现在,如果您为分钟参数指定
15
,它将在每小时 15 分钟运行脚本 - 但无法每 15 分钟指定一次,除非我支持像 */15
这样的参数值。
您正在编写一个操作文本的工具。 shell 是一种操作(创建/销毁)文件和进程以及对其他工具的调用顺序的工具。用于通用文本操作的强制性 POSIX(在所有 Unix 机器上可用)工具是 awk。因此,要使用 shell 操作文本,正确的方法是编写 awk 脚本来进行文本操作,然后 shell 脚本主要只是调用 awk 来解释 awk 脚本。
如果需要,您可以将 awk 输出读入 bash 标量变量或数组,以便稍后在 shell 脚本中使用它们。如果您需要使用 shell 执行其他操作,但如果您只是操作文本,那么只需在 awk 中完成所有操作即可。
以下是如何扩展数字和字符串范围的开始:
$ cat tst.sh
#!/usr/bin/env bash
expand() {
awk -v dowNums="$1" -v monthNums="$2" -v dowStrs="$3" -v monthStrs="$4" '
BEGIN {
printf "dowNums\t\"%s\"\t-> \"%s\"\n", dowNums, expandNums(dowNums,1,7)
printf "monthNums\t\"%s\"\t-> \"%s\"\n", monthNums, expandNums(monthNums,1,12)
printf "dowStrs\t\"%s\"\t-> \"%s\"\n", dowStrs, expandStrs(dowStrs,"Mon Tue Wed Thu Fri Sat Sun")
printf "monthStrs\t\"%s\"\t-> \"%s\"\n", monthStrs, expandStrs(monthStrs,"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
}
function expandNums(spec,minBeg,maxEnd, \
beg,end,range,i,list) {
if ( spec == "" ) {
return
}
if ( spec ~ /^[^*-]+$/ ) {
beg = spec
end = beg
}
else if ( spec == "*" ) {
beg = minBeg
end = maxEnd
}
else if ( split(spec,range,"-") == 2 ) {
beg = range[1]
end = range[2]
}
if ( ( beg+0 == beg ) &&
( end+0 == end ) &&
( beg <= end ) &&
( (minBeg <= beg) && (beg <= maxEnd) ) &&
( (minBeg <= end) && (end <= maxEnd) ) )
{
for ( i=beg; i<=end; i++ ) {
list = list i (i<end ? OFS : "")
}
}
if ( list == "" ) {
printf "Bad spec: \"%s\"\n", spec |"cat>&2"
}
return list
}
function expandStrs(spec,vals, \
idxs2vals,vals2idxs,minBeg,maxEnd,beg,end,range,i,list) {
if ( spec == "" ) {
return
}
minBeg = 1
maxEnd = split(vals,idxs2vals," ")
for ( i in idxs2vals) {
vals2idxs[idxs2vals[i]] = i
}
if ( spec ~ /^[^*-]+$/ ) {
beg = ( spec in vals2idxs ? vals2idxs[spec] : "" )
end = beg
}
else if ( spec == "*" ) {
beg = minBeg
end = maxEnd
}
else if ( split(spec,range,"-") == 2 ) {
beg = ( range[1] in vals2idxs ? vals2idxs[range[1]] : "" )
end = ( range[2] in vals2idxs ? vals2idxs[range[2]] : "" )
}
if ( ( beg+0 == beg ) &&
( end+0 == end ) &&
( beg <= end ) &&
( (minBeg <= beg) && (beg <= maxEnd) ) &&
( (minBeg <= end) && (end <= maxEnd) ) )
{
for ( i=beg; i<=end; i++ ) {
list = list idxs2vals[i] (i<end ? OFS : "")
}
}
if ( list == "" ) {
printf "Bad spec: \"%s\"\n", spec |"cat>&2"
}
return list
}
'
}
echo "Varying day of week number specs"
expand '4' '' '' ''
expand '3-6' '' '' ''
expand '*' '' '' ''
echo ""
echo "Varying month number specs"
expand '' '4' '' ''
expand '' '3-6' '' ''
expand '' '*' '' ''
echo ""
echo "Varying day of week abbreviation specs"
expand '' '' 'Tue' ''
expand '' '' 'Wed-Fri' ''
expand '' '' '*' ''
echo ""
echo "Varying month abbreviation specs"
expand '' '' '' 'Apr'
expand '' '' '' 'Mar-Jun'
expand '' '' '' '*'
$ ./tst.sh
Varying day of week number specs
dowNums "4" -> "4"
monthNums "" -> ""
dowStrs "" -> ""
monthStrs "" -> ""
dowNums "3-6" -> "3 4 5 6"
monthNums "" -> ""
dowStrs "" -> ""
monthStrs "" -> ""
dowNums "*" -> "1 2 3 4 5 6 7"
monthNums "" -> ""
dowStrs "" -> ""
monthStrs "" -> ""
Varying month number specs
dowNums "" -> ""
monthNums "4" -> "4"
dowStrs "" -> ""
monthStrs "" -> ""
dowNums "" -> ""
monthNums "3-6" -> "3 4 5 6"
dowStrs "" -> ""
monthStrs "" -> ""
dowNums "" -> ""
monthNums "*" -> "1 2 3 4 5 6 7 8 9 10 11 12"
dowStrs "" -> ""
monthStrs "" -> ""
Varying day of week abbreviation specs
dowNums "" -> ""
monthNums "" -> ""
dowStrs "Tue" -> "Tue"
monthStrs "" -> ""
dowNums "" -> ""
monthNums "" -> ""
dowStrs "Wed-Fri" -> "Wed Thu Fri"
monthStrs "" -> ""
dowNums "" -> ""
monthNums "" -> ""
dowStrs "*" -> "Mon Tue Wed Thu Fri Sat Sun"
monthStrs "" -> ""
Varying month abbreviation specs
dowNums "" -> ""
monthNums "" -> ""
dowStrs "" -> ""
monthStrs "Apr" -> ""
Bad spec: "Apr"
dowNums "" -> ""
monthNums "" -> ""
dowStrs "" -> ""
monthStrs "Mar-Jun" -> ""
Bad spec: "Mar-Jun"
dowNums "" -> ""
monthNums "" -> ""
dowStrs "" -> ""
monthStrs "*" -> "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"