1

我是 bash 脚本的新手,我正在尝试编写一些代码来解析和操作我正在处理的文件。

我需要为文件中的一堆不同时间增加和减少时间的分钟。我的问题发生在例如 2:04 或 14:00 时。

文件示例:

2:43
2:05
15:00

我当前的 bash 脚本摘录是这样的

for x in `cat $1`;
  do minute_var=$(echo $x | cut -d: -f2);
  incr_min=$(($minute_var + 1 | bc));
  echo $incr_min;
done

当前结果:

44
6
1

要求的结果:

44
06
01

有什么建议么

4

8 回答 8

3

使用printf

incr_min=$(printf %02d $(($minute_var + 1 )) )

不,bc如果只涉及整数,则不需要。

于 2013-05-24T14:25:27.690 回答
1
while IFS=: read hour min; do 
    printf "%02d\n" $((10#$min + 1))
done <<END
2:43
2:05
15:00
8:08
0:59
END
44
06
01
09
60

对于下一小时的分钟换行,请使用具有时间功能的语言,例如 gawk

awk -F: '{
    time = mktime("1970 01 01 " $1 " " $2 " 00")
    time += 60
    print strftime("%M", time)
}' 
perl -MTime::Piece -MTime::Seconds -nle '
    $t = Time::Piece->strptime($_, "%H:%M");
    print +($t + ONE_MINUTE)->strftime("%M");
'
于 2013-05-24T18:46:24.237 回答
1

这可以满足您的要求吗?

kent$  echo "2:43
2:05
15:00"|awk -F: '{$2++;printf "%02d\n", $2}'
44
06
01
于 2013-05-24T14:25:22.440 回答
1

更新#2

你的脚本有一些问题。首先,`cat file`您应该使用 `<file`or 而不是$(<file). 只需打开文件即可免去一fork通电话。另一方面,调用and (and ) 也不需要,因为内部具有适当的功能。因此,您可以再次节省一些s 和s。execbashcutbcprintfbashforkexec

如果输入文件很大(大于 cca 32 KiB),则for-loop 行可能太大而无法处理,bash因此我建议改用while-loop 并逐行读取文件。

我可以在纯bash(应用 Atle 的 substr 解决方案)中提出类似的建议:

while IFS=: read hr min; do
  incr_min=$((1$min+1)); #Octal problem solved
  echo ${incr_min: -2}; #Mind the space before -2!
  #or with glennjackman's suggestion to use decimal base
  #incr_min=0$((10#$min+1))
  #echo ${incr_min: -2};
  #or choroba's solution improved to set variable directly
  #printf -v incr_min %02d $((10#$min+1))
  #echo $incr_min
done <file

输入文件

$ cat file
2:43
2:05
15:00
12:07
12:08
12:09

输出:

44
06
01
08
09
10

也许这printf -v是最简单的,因为它只需一步即可将结果放入变量中。

tripleee如果结果为 60 会发生什么,这是一个很好的问题。

于 2013-05-24T15:21:17.133 回答
0

尝试这个:

for x in $(<$1); do
    printf "%02d\n" $(((${x#*:}+1)%60));
done
于 2013-09-26T04:17:48.863 回答
0

这是一个解决方案

  • 将秒数从 59 包装到 0
  • 完全符合 POSIX 标准——没有 bashisms!
  • 不需要一个叉子因此非常快
$ cat x
2:43
2:05
2:08
2:09
15:00
15:59
$ while IFS=: read hr min; do
   printf '%02d\n' $(((${min#0}+1)%60))
done < x
44
06
09
10
01
00
于 2013-05-25T13:28:34.843 回答
0

用于printf将输出重新格式化为零填充、2 宽:

incr_min=$(printf %02d $incr_min)
于 2013-05-24T14:25:57.827 回答
-1

Padding with 0, and getting two last characters:

for x in `cat $1`;
  do minute_var=$(echo $x | cut -d: -f2);
  incr_min=0$(($minute_var + 1 | bc));
  echo ${incr_min: -2:2};
done
于 2013-05-24T15:02:59.700 回答