Bash -将时间间隔字符串转换为单位秒



我正在尝试将描述时间间隔的字符串转换为相应的秒数。

经过一些实验,我发现我可以这样使用date:

soon=$(date -d '5 minutes 10 seconds' +%s); now=$(date +%s)
echo $(( $soon-$now ))

,但我认为应该有一个更简单的方法来转换字符串,如"5分钟10秒"到相应的秒数,在这个例子310。是否有办法在一个命令中做到这一点?

注意:虽然可移植性很有用,但它不是我的首要任务。

可以从epoch

开始
date -d"1970-01-01 00:00:00 UTC 5 minutes 10 seconds" "+%s"
310

你也可以很容易地把times

Time="1 day"
date -d"1970-01-01 00:00:00 UTC $Time" "+%s"
86400

有一种方法可以做到这一点,在纯bash中不使用date命令(为了可移植性)

假设您只有一个输入字符串来转换bash变量中的"5分钟10秒",:分隔符如下所示。

$ convertString="00:05:10"
$ IFS=: read -r hour minute second <<< "$convertString"
$ secondsValue=$(((hour * 60 + minute) * 60 + second))
$ printf "%sn" "$secondsValue"
310

您可以直接在命令行上运行上述命令,而不需要使用$标记。

这样做(添加epoch 19700101):

$ date -ud '19700101 5 minutes 10 seconds' +%s
310

添加-u以避免本地时间(和夏令时)影响是很重要的。

$ TZ=America/Los_Angeles date -d '19700101 5 minutes 10 seconds' +%s
29110

注意date可以做一些数学运算:

$ date -ud '19700101 +5 minutes 10 seconds -47 seconds -1 min' +%s
203

前面的建议在alpine linux上不能正常工作,所以这里有一个小的辅助函数,它是POSIX兼容的,易于使用,还支持计算(只是作为实现的副作用)。

函数总是根据所提供的形参返回一个整数。

$ durationToSeconds '<value>' '<fallback>'
$ durationToSeconds "1h 30m"
5400
$ durationToSeconds "$someemptyvar" 1h
3600
$ durationToSeconds "$someemptyvar" "1h 30m"
5400
# Calculations also work
$ durationToSeconds "1h * 3"
10800
$ durationToSeconds "1h - 1h"
0
# And also supports long forms for year, day, hour, minute, second
$ durationToSeconds "3 days 1 hour"
262800
# It's also case insensitive
$ durationToSeconds "3 Days"
259200
function durationToSeconds () {
  set -f
  normalize () { echo $1 | tr '[:upper:]' '[:lower:]' | tr -d ""\'" | sed 's/years{0,1}/y/g; s/months{0,1}/m/g; s/days{0,1}/d/g; s/hours{0,1}/h/g; s/minutes{0,1}/m/g; s/min/m/g; s/seconds{0,1}/s/g; s/sec/s/g;  s/ //g;'; }
  local value=$(normalize "$1")
  local fallback=$(normalize "$2")
  echo $value | grep -v '^[-+*/0-9ydhms]{0,30}$' > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    >&2 echo Invalid duration pattern "$value"
  else
    if [ "$value" = "" ]; then
      [ "$fallback" != "" ] && durationToSeconds "$fallback"
    else
      sedtmpl () { echo "s/([0-9]+)$1/(01 * $2)/g;"; }
      local template="$(sedtmpl '( |$)' 1) $(sedtmpl y '365 * 86400') $(sedtmpl d 86400) $(sedtmpl h 3600) $(sedtmpl m 60) $(sedtmpl s 1) s/) *(/) + (/g;"
      echo $value | sed "$template" | bc
    fi
  fi
  set +f
}

编辑:是。我在评论后为OP开发了,并在Mac OS X, CentOS和Ubuntu上进行了检查。一个线性的POSIX兼容命令,用于将"X分钟Y秒"格式转换为秒。这就是问题所在

echo $(($(echo "5 minutes 10 seconds" | cut -c1-2)*60  + $(echo "5 minutes 10 seconds" | cut -c1-12 | awk '{print substr($0,11)}')))

OP通过评论告诉我,他想要"X分Y秒"格式,而不是HH:MM:SS格式。带有date"+%s"的命令在(我的)Mac上抛出错误。OP想要从"X分钟Y秒"格式中获取数值并将其转换为秒。首先,我以数字形式提取分钟(将其作为方程A):

echo "5 minutes 10 seconds" | cut -c1-2)

然后我提取第二部分(把它作为方程B):

echo "5 minutes 10 seconds" | cut -c1-12 | awk '{print substr($0,11)}'

现在将分钟乘以60,然后与另一个相加:

echo $((equation A)*60) + (equation B))

OP应该要求其他人检查我的开发版本(但工作)命令,然后再使用它进行自动重复使用,就像我们在生产服务器上使用cron一样。

如果我们想在一个日志文件上运行它,它的值是"X分钟Y秒"格式,我们必须将echo "5 minutes 10 seconds"更改为cat file | ...类似的命令。我也保留了它的要点,如果我或其他人需要,我们可以使用它与cat运行在服务器日志文件与x minutes y seconds类似的日志格式。

虽然离题(我所理解的,问题与当前时间没有太大关系),但这不适用于posix兼容的操作系统以秒为单位获取当前时间:

date -d "1970-01-01 00:00:00 UTC 5 minutes 10 seconds" "+%s"

它会在MacOS X上抛出错误,但在大多数GNU/Linux发行版上都可以工作。+%s部分在posix兼容的操作系统上复杂使用时会抛出错误。这些命令主要适用于在POSIX兼容的任何类型的unix(如OS)上以秒为单位获取当前时间:

awk 'BEGIN{srand(); print srand()}'
perl -le 'print time' 

如果OP需要,可以通过生成以秒为单位的当前时间并减去来扩展它。我希望它会有所帮助。

----编辑前的旧答案----

你可以得到当前的时间没有dateecho | awk '{print systime();}'wget -qO- http://www.timeapi.org/utc/now?\s。另一种将时间转换为秒的方法是echo "00:20:40.25" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'

在另一个答案中显示的printf的示例近乎完美。

你想要的东西总是GNU/Linux的基本实用程序所需要的- gnu.org/../../../../../Setting-an-Alarm.html

接近的方式真的取决于你需要多少万无一失的方式。

相关内容

  • 没有找到相关文章

最新更新