我正在尝试加速我的脚本,目前大约需要30秒。我是bash的新手,我确信我正在使用一些糟糕的脚本练习(在https://unix.stackexchange.com/a/169765中找到了一些提示,但仍无法解决我的问题)。
我需要做的是从外部文件中获取数据,并将数字提取到两个数组中。我的脚本运行正常,但速度太慢。
readData=`cat $myfile`
# readData = [[1491476100000,60204],[1491476130000,59734],...,[1491476160000,60150]]
# I have approximately 5000 points (two numbers in each point)
pointTime=()
pointVal=()
for line in `echo $readData | grep -Po "[0-9]+,[0-9]+"`; do
# Get first number but drop last three zeroes (e.g. 1491476100)
pointTime+=(`echo $line | grep -Po "^[0-9]+" | sed "s/\(.*\)000$/\1/"`)
# Get second number, e.g. 60204
pointVal+=(`echo $line | grep -Po "[0-9]+$"`)
done
也许我可以在参数扩展中使用一些正则表达式,但我不知道如何。
答案 0 :(得分:2)
以下是我编写脚本的方法:
mapfile -t points < <(grep -Po '\d+,\d+' "$myfile")
pointTime=("${points[@]%000,*}")
pointVal=("${points[@]#*,}")
甚至
mapfile -t pointTime < <(grep -Po '\d+(?=000,)' "$myfile")
mapfile -t pointVal < <(grep -Po ',\K\d+' "$myfile")
当您确定文件格式正确时。
您已经确定了主要问题:循环速度很慢,尤其是因为循环内部调用了很多程序。不过,这里有一些提示,你可以如何改进你的脚本而不丢弃循环。有些部分不必要地复杂化,例如
readData=`cat $myfile`
`echo $readData | grep -Po "[0-9]+,[0-9]+"`
可以写成
grep -Po "[0-9]+,[0-9]+" "$myfile"
和
echo $line | grep -Po "^[0-9]+" | sed "s/\(.*\)000$/\1/"
可以写成
grep -Po "^[0-9]+(?=000)" <<< "$line"
使用bash的匹配运算符=~
代替grep
可以大大加快速度,因为启动grep
的速度很慢。
[[ "$line" =~ (.*)000,(.*) ]]
pointTime+=("${BASH_REMATCH[1]}")
pointTime+=("${BASH_REMATCH[2]}")
答案 1 :(得分:2)
我怀疑将结果存储在数组中的要求。您可能实际上想要成对循环遍历值。无论如何,将中间值存储在内存中是不优雅和浪费的。
grep -Eo '[0-9]+,[0-9]+' "$myfile" |
while IFS=, read -r first second, do
process value pair "${first%000}" "$second"
done
如果您坚持将值存储在数组中,那么如何更改循环体应该是显而易见的。
pointTime+=("${first%000}")
pointVal+=("$second")