我目前正在处理一个处理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
基本上检查时间值是否均匀,然后执行转换。
答案 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解决方案不能。