首页 > 解决方案 > 在不使用 awk 的情况下编写 bash 脚本?

问题描述

我们被要求编写一个shell 脚本,它将玩家记录的输入作为标准输入。

样本输入:

id|name|time
23|Jordan|45:17
14|Jason|4:50
12|Bryan|
24|Cody|00:12
33|kobe|41
55|rocky|0

我们需要读取脚本中的每条记录skip header),然后通过以秒为单位转换时间并从“|”更改分隔符来输出每个对应的记录 ''空格)。

正如我们在上面的示例测试用例中看到的,一些记录有空的时间字段第三条记录),因为那些以秒为单位的记录时间将被视为0

样例输出:

23 Jordan 2717
14 Jason 290
12 Bryan 0
24 Cody 12
33 kobe 2460
55 rocky 0

my_solution_script.sh

#!/bin/bash


read -r header
while IFS="|" read -r pid pname time || [[ -n $pid ]]
do  
    min=$(cut -d ':' -f 1 <<< "$time")
    sec=$(cut -d ':' -f 2 <<< "$time")
    ((min*=60))
    ((min+=sec))
    
    echo "$pid $pname $min"
done

错误输出:

23 Jordan 2717
14 Jason 290
12 Bryan 0
24 Cody 12
33 kobe 2501
55 rocky 0

正如我们所见,上面的脚本为第 5 条记录提供了错误的输出

如何修复上述脚本,以在每种情况下获得正确的输出?

我认为使用awk可能有一个更简单的解决方案,但我现在对“awk 脚本”不太了解,所以我正在寻找一种使用基本 shell 命令解决这个问题的方法,不过awk 命令解决方案也是欢迎。

谢谢你。

标签: linuxbashshellunixawk

解决方案


问题是当它不包含分隔符时cut -d: -f2 <<< "$time"返回所有。所以对于科比来说,你是在计算而不是仅仅。$time:41*60+4141*60

因此,您需要在尝试获取秒数之前检查是否$time包含 a 。:

read -r header
while IFS="|" read -r pid pname time || [[ -n $pid ]]
do  
    min=$(cut -d ':' -f 1 <<< "$time")
    if [[ $time =~ : ]]
        sec=$(cut -d ':' -f 2 <<< "$time")
    else
        sec=0
    fi
    ((min*=60))
    ((min+=sec))
    
    echo "$pid $pname $min"
done

推荐阅读