bash:时间表和循环脚本

bash:时间表和循环脚本,bash,Bash,我是一个狂欢节爱好者。我写了很多剧本,但这次我觉得这个对我来说太大了。我正在编写一个脚本,该脚本将根据文件中的时间表检查小时数,并将其汇总 我有一份每周日程安排的文件。通过使用grep,它会返回我的时间表(例如13:00-20:30或13:30-21:30)。这些文件总是以相同的格式出现,只是时间不同,所以我的grep查询总是有效的。唯一的区别是,有时它将返回四行(含小时),有时更少,有时更多,这取决于给定文件中的内容(如果行数很重要,我总是可以使用grep-c) 当我从开始时间中减去结束时间时

我是一个狂欢节爱好者。我写了很多剧本,但这次我觉得这个对我来说太大了。我正在编写一个脚本,该脚本将根据文件中的时间表检查小时数,并将其汇总

我有一份每周日程安排的文件。通过使用grep,它会返回我的时间表(例如13:00-20:30或13:30-21:30)。这些文件总是以相同的格式出现,只是时间不同,所以我的grep查询总是有效的。唯一的区别是,有时它将返回四行(含小时),有时更少,有时更多,这取决于给定文件中的内容(如果行数很重要,我总是可以使用grep-c)

当我从开始时间中减去结束时间时,结果是正确的,尽管如果时间有点奇怪(例如14:00-16:17),它将不起作用。我怎样才能做到这一点(2小时17分钟)

然后我想我应该使用一个循环。我尝试了几件事,但非常困惑,决定来这里

这是我到目前为止得到的(8月26日至31日显然是时间表文件)

我希望脚本回显这些行中的每一行,告诉我每行有多少小时,然后将它们全部添加到一起

我应该使用For循环吗?我应该在循环中使用函数吗


我会告诉你答案。

这可能不是你想听到的,但在这种情况下,不同的编程语言肯定会比Bash算法工作得更好。例如,在Python中,只需执行
duration=finish-start
。这将进行时区感知、闰日感知、理智的计算,从而生成一个对象,从中可以获得从年到小数秒的所有信息。

是的,您将使用循环。您应该以秒为单位维护运行总数,并在最终输出中将其转换为小时:分钟

第一个想法(警告,此代码包含错误)

bash可以使用
read
命令将空格分隔的字符串解析为单词

臭虫在哪里?使用bash的默认配置,管道中的每个命令都在单独的子shell中执行。因此,当运行
循环结束的子shell时,
total
变量的内容将丢失

有两种方法可以解决这个问题:

  • 将输出命令分组到相同的子shell中

    total=0
    grep '[0-9][0-9]:[0-9][0-9]' 26to31August | {
        while read -r start x finish x; do
            a=$( date -d "$start" "+%s" )
            b=$( date -d "$finish" "+%s" )
            (( total += b - a ))
        done
        hours=$(( total / 3600 ))
        minutes=$(( (total % 2600) / 60 ))
        printf "%d:%02d\n" $hours $minutes
    }
    
  • 不要使用管道,重定向管道的输出 进入while循环

    total=0
    
    while read -r start x finish x; do
        a=$( date -d "$start" "+%s" )
        b=$( date -d "$finish" "+%s" )
        (( total += b - a ))
    done < <( grep '[0-9][0-9]:[0-9][0-9]' 26to31August )
    
    hours=$(( total / 3600 ))
    minutes=$(( (total % 2600) / 60 ))
    printf "%d:%02d\n" $hours $minutes
    
    total=0
    读取时-r开始x结束x;做
    a=$(日期-d“$start”“+%s”)
    b=$(日期-d“$finish”“+%s”)
    ((总计+=b-a))
    
    done<
    expr
    是20世纪70年代的一种古老工具。使用
    $(…)
    进行现代(1991年后)shell中的内置算法。避免使用所有caps变量名——根据POSIX规范,它们用于对shell和操作系统实用程序有意义的变量,而至少有一个小写字符的名称保证应用程序可以安全使用;看,第四段……也就是说,所问的问题相当广泛;这不是“这是一个狭隘的技术问题”(这是我们最擅长的!),而是“你会建议我如何解决这个问题?”——天生对许多解决方案持开放态度……也就是说,你熟悉模运算吗?如果你把除法的剩余部分,你可以把它分成几分钟;取剩下的,你就有秒数了。
    total=0
    grep '[0-9][0-9]:[0-9][0-9]' 26to31August | {
        while read -r start x finish x; do
            a=$( date -d "$start" "+%s" )
            b=$( date -d "$finish" "+%s" )
            (( total += b - a ))
        done
        hours=$(( total / 3600 ))
        minutes=$(( (total % 2600) / 60 ))
        printf "%d:%02d\n" $hours $minutes
    }
    
    total=0
    
    while read -r start x finish x; do
        a=$( date -d "$start" "+%s" )
        b=$( date -d "$finish" "+%s" )
        (( total += b - a ))
    done < <( grep '[0-9][0-9]:[0-9][0-9]' 26to31August )
    
    hours=$(( total / 3600 ))
    minutes=$(( (total % 2600) / 60 ))
    printf "%d:%02d\n" $hours $minutes