我如何使用sed或awk来更正日志时间格式

时间:2012-12-01 20:09:39

标签: file bash csv sed awk

我目前正在处理一个处理csv文件的脚本,并在整个过程中纠正它们的某些方面。如果需要,它所做的一件事是正确的时间格式。发生了两种类型的转换:

 xx:xx:xx to PTxxHxxMxxS
 10:03:45 to PT10H03M45S

我已经能够使用以下内容(见下文)做到这一点,虽然我试图找到如何使用sed或awk来加速这个过程。除了实际的转换过程之外,我还想继续计算所做的更改(所以说4次转换值,计数器将增加到4),我已经能够轻松地使用if下面的声明(虽然没有显示),虽然我不太了解使用sed / awk这样做。

 istimef=$( echo "$Sfcpp6" | grep ".*:.*:.*" )
                    if [ "$istimef" != "" ]; then
                            hs=$( echo "$Sfcpp6" | cut -d ':' -f 1 )
                            mn=$( echo "$Sfcpp6" | cut -d ':' -f 2 )
                            sc=$( echo "$Sfcpp6" | cut -d ':' -f 3 )
                            Sfcpp6=$( echo "PT"$hs"H"$mn"M"$sc"S" )
                            echo "$Sfcp6"
                    fi

基本上检查时间值是否均匀,然后执行转换。

4 个答案:

答案 0 :(得分:2)

令人惊讶的是,您完成此任务需要多少进程和子shell!我会一直对人们的聪明才智和创造力感到惊讶。我计算了10个子壳,4个生成过程。

看,你可以实现完全相同而不会产生一个进程而且没有任何子shell。我们在这里谈论加速!

第一个任务,给定xx:yy:zz形式的字符串,尽可能有效地将其转换为PTxxHyyMzzS(只看一个命令!和内置!没有sed!) :

$ string='12:34:56'
$ printf -v transformed 'PT%sH%sM%sS' ${string//:/ }
$ # Done! Don't believe me?
$ echo "$transformed"
PT12H34M56S

现在,在执行此操作之前,您可能想要检查字符串是否为xx:yy:zz形式。退出grep。只需测试一下:

if [[ "$string" = *:*:* ]]; then
    echo "ok"
else
    echo "not ok"
fi

因此,您向我们展示的脚本部分将更加高效:

if [[ "$Sfcpp6" = *:*:* ]]; then
    printf -v Sfcp6 'PT%sH%sM%sS' ${Sfcpp6//:/ }
    echo "$Sfcp6"
fi

总计:0个子shell,产生了0个进程。

或者,如果您的目标只是回显变换后的字符串:

if [[ "$Sfcpp6" = *:*:* ]]; then
    printf 'PT%sH%sM%sS\n' ${Sfcpp6//:/ }
fi

答案 1 :(得分:1)

sed解决方案:使用\(...\)捕获数字,字符类[0-9]以匹配任何数字。

sed 's/\([0-9][0-9]\):\([0-9][0-9]\):\([0-9][0-9]\)/PT\1H\2M\3S/'

答案 2 :(得分:0)

如果您想计算替换行:

perl -pe '
    END{print "count=$count\n"}
    s/(\d{2}):(\d{2}):(\d{2})/PT$1H$2M$3S/ && $count++
' file.txt

答案 3 :(得分:0)

由@choroba发布的这个sed解决方案的GNU awk等价物:

sed 's/\([0-9][0-9]\):\([0-9][0-9]\):\([0-9][0-9]\)/PT\1H\2M\3S/'

会非常相似:

awk '{print gensub(/([0-9][0-9]):([0-9][0-9]):([0-9][0-9])/,"PT\\1H\\2M\\3S","")}'

但awk解决方案可以通过简单的修改来解决您的问题“是否可以让sed继续计算它所做的更改?”:

awk '{orig=$0; $0=gensub(/([0-9][0-9]):([0-9][0-9]):([0-9][0-9])/,"PT\\1H\\2M\\3S",""); print} $0 != orig{count++} END{printf "%d changes made.\n",count}'

虽然sed解决方案不能。