Bash检查$ var是否在数字范围内

时间:2015-03-24 12:16:03

标签: linux bash time range

我做了一个bash函数,它有2个参数。

$1 = start time
$2 = end time

这两个值均以小时为单位,因此它们可以从0023

这个想法是函数接受开始和结束时间参数,并在这个时间范围内播放一些视频片段。

我首先提出了这个问题:

TIME=$(date +%H)

# # #
#
#  Check if its time to play files
#  $1 = begin hour, $2 = End hour, $3 = folder with video files
#
# # #
check_if_time_to_play(){
# If current TIME is between begin and end time
if [ $TIME -ge "$1" ] &&  [ $TIME -lt "$2" ]; then
    # Make sure the folder is not empty
    if find "$3" -mindepth 1 -print -quit | grep -q .; then
        # It's not emty, play the clips
        play_files "$3" 
    else
        continue # It's empty! dont play the non-existing clips
    fi
else
   continue # TIME is not in range, dont play the clips
fi
} 

但我很快意识到这不是现在的。

如果我提交,请说$1=22$2=05$TIME=23这些片段不会播放。

所以我考虑在最后if声明中添加额外的else

这样的事情:

# check for times where start is bigger than end (ie. 22-05)
if [ "$2" -le "$1" ]; then
    #and in here do some range check

fi

所以在if内部我正在考虑做一些范围检查,但我不确定如何做到这一点。

我在想这样的事情:

if [[ $TIME -eq {$1..24} ] ]&&  [ $TIME -eq {00..$2} ]; then
    play_files "$3" 
fi

所以这个offcause不起作用 - 所以我的问题是: 有什么方法可以针对一系列数字检查0023吗?

或者如果你明白我想做什么,有没有更好的方法?

如果你不明白,请告诉我 - 我会尝试解释一下。

提前致谢!

2 个答案:

答案 0 :(得分:3)

尝试以下操作,使用 bash的shell arithmetic ,在多个上下文中使用熟悉的C风格语法提供算术评估

  • 作为测试计算,无输出,格式为((...))let ...
  • 作为计算$((...))
  • 的形式输出结果(算术扩展
  • 使用<{1}}或declare -i
  • 声明的整数变量声明
  • 在bash期望数字的其他上下文中,例如数组下标子串索引
local -i

示例调用:

# # #
#
#  Check if its time to play files
#  $1 = hour now, $2 = begin hour, $3 = End hour, $4 = folder with video files
#
# # #
check_if_time_to_play() {

  # Make sure the arguments are interpreted as *decimal* integers
  # by evaluating them in an arithmetic context (-i) with prefix '10#', 
  # indicating number base 10.
  # (A leading '0' would cause intepretation as *octal*.)
  local -i hourNow=10#$1 startHour=10#$2 endHour=10#$3 play
  local dir=$4

  # Make sure the folder is not empty.
  if ! find "$dir" -mindepth 1 -print -quit | grep -q .; then
    return # It's empty! Don't play the non-existing clips. 
  fi

  # Determine if current hour is between begin and end time.
  play=0
  if (( startHour < endHour )); then
    if (( hourNow >= startHour && hourNow < endHour )); then
      play=1
    fi
  else # startHour > endHour: overnight hours
    if (( hourNow >= startHour || hourNow < endHour )); then
      play=1
    fi
  fi

  if (( play )); then
    # Play the clips
    play_files "$dir" 
  else
     : # Current hour is not in range, don't play the clips.
  fi
}
  • 请注意,我已将当前时间作为第一个参数。 (另外,最好避免使用全大写的shell变量名称,例如check_if_time_to_play $(date +%H) 22 05 . # Hard-coded, to test logic check_if_time_to_play 23 22 05 . check_if_time_to_play 11 10 18 . ,以避免与环境或特殊shell变量发生冲突。)
  • TIME 输出计算结果,而$((...))将结果解释为 test
  • 开始时间的情况&gt;结束时间(隔夜)时间帧在单独的((...))分支中处理,其中当前小时必须 晚于之前的第二天上午结束时间。

答案 1 :(得分:2)

为什么不使用完整日期? GNU date(Linux上可用的那个)有一个漂亮的-d开关,可让您打印任意时间。如果您给它一个小时,它将打印该小时的完整日期今天

$ date -d 23:00
Tue Mar 24 23:00:00 EET 2015

您可以告诉它打印自纪元以来的秒数,以便于比较:

$ date -d 23:00 +%s
1427230800

最后,您可以假设如果结束日期小于开始日期,那么该结束日期将指明天。考虑到这一点,脚本的工作版本可能是:

#!/usr/bin/env bash
TIME=$(date +%s)

check_if_time_to_play(){
# If current TIME is between begin and end time
if [ $TIME -ge "$1" ] &&  [ $TIME -lt  "$2" ]; then
    # Make sure the folder is not empty
    if find "$3" -mindepth 1 -print -quit | grep -q .; then
        # It's not emty, play the clips
        #play_files "$3" 
        echo playing
    fi
else
    echo "Out of range: $TIME : $1 : $2"
fi

} 
## Get the start and end times
start="$(date -d "$1" +%s)"
end="$(date -d "$2" +%s)"

## Deal with end times that are smaller than start times.
## We will assume that they refer to tomorrow's date.
[ "$start" -gt "$end" ] && end="$(date -d "$2 + 1 day" +%s)"

check_if_time_to_play "$start" "$end" "$3"

请注意,我删除了else continue块,因为它们在if语句中没有意义。