使用Bash脚本从JSON计算IN/OUT事件累计时长的技术求助
解决IN到OUT时间间隔累加问题的脚本修改方案
嘿,我帮你调整了脚本,现在只会计算IN到对应OUT的时间间隔,还能处理最后一个事件是IN的特殊情况(自动和当前时间算差值)。先看修改后的完整脚本:
#!/bin/bash JSON='{ "times": [ [ "7:43", "IN" ], [ "8:26", "OUT" ], [ "8:27", "IN" ], [ "9:12", "OUT" ], [ "9:14", "IN" ], [ "9:22", "OUT" ], [ "9:23", "IN" ], [ "12:12", "OUT" ], [ "13:12", "IN" ] ]}' # 将IN和OUT时间分别存入bash数组 readarray -t IN_TIMES < <(jq -r '.times[] | select(.[1] == "IN") | .[0]' <<< "$JSON") readarray -t OUT_TIMES < <(jq -r '.times[] | select(.[1] == "OUT") | .[0]' <<< "$JSON") total_seconds=0 # 遍历每一对IN-OUT计算间隔 for ((i=0; i<${#OUT_TIMES[@]}; i++)); do in_time=${IN_TIMES[$i]} out_time=${OUT_TIMES[$i]} # 转换为时间戳计算秒差 in_epoch=$(date +%s -d "$in_time") out_epoch=$(date +%s -d "$out_time") diff_sec=$((out_epoch - in_epoch)) # 格式化输出间隔,并累加总时长 formatted_diff=$(date +%H:%M -ud @$diff_sec) echo "From $in_time (IN) to $out_time (OUT): $formatted_diff" total_seconds=$((total_seconds + diff_sec)) done # 检查是否存在未配对的最后一个IN事件 if (( ${#IN_TIMES[@]} > ${#OUT_TIMES[@]} )); then last_in_time=${IN_TIMES[-1]} current_epoch=$(date +%s) last_in_epoch=$(date +%s -d "$last_in_time") diff_sec=$((current_epoch - last_in_epoch)) formatted_diff=$(date +%H:%M -ud @$diff_sec) echo "From $last_in_time (IN) to current time: $formatted_diff" total_seconds=$((total_seconds + diff_sec)) fi # 输出总时长 echo "Total accumulated time: $(date +%H:%M -ud @$total_seconds)"
关键改动说明:
- 成对提取时间:用
readarray把IN和OUT的时间分别存入bash数组,这样每一个IN_TIMES[i]都对应OUT_TIMES[i],直接配对计算,避免了原脚本遍历所有相邻时间的问题。 - 精准筛选事件:把原脚本的
contains("IN")改成== "IN",避免匹配到带空格的无效事件(比如你原数据里的"IN ",如果实际数据有这类格式,可以改回contains("IN"),但建议统一事件格式)。 - 处理未配对的IN:通过比较IN和OUT数组的长度,判断是否存在最后一个未配对的IN,自动计算它到当前时间的差值。
- 累加总时长:新增了总时长的计算,方便直接得到所有有效间隔的总和。
原脚本的核心问题:
原脚本遍历了所有相邻时间戳,包括OUT到IN的间隔,这正是你不需要的部分。改成数组配对后,只处理IN到对应OUT的间隔,完美契合你的需求~
内容的提问来源于stack exchange,提问作者tzippy
相关产品推荐
相关产品推荐

