2017-04-11 364 views
0

我想加快我的腳本,目前大約需要30秒。我是bash的新手,我確信我正在使用一些不好的腳本練習(在https://unix.stackexchange.com/a/169765中發現了一些提示,但仍無法解決我的問題)。緩慢bash腳本使用grep和sed

我需要做的是從外部文件中獲取數據,並將數字提取到兩個數組中。我的腳本工作正常,但速度太慢。

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

如果你能告訴我們品嚐INPUT_FILE和預期的輸出,我們可以幫助更多的相同,則 – RavinderSingh13

+0

你可以找到已經你問如上面的代碼中的註釋 –

+1

你打算用數據做一旦你把它加載到數組中? Bash將成爲處理這些數據的絕佳選擇,這一點並不完全清楚。例如,請注意您的輸入文件是有效的JSON。大多數任何語言都可以通過簡單的方式將其加載到本地數據結構中,或者甚至可以直接在JavaScript中對其進行操作。 –

回答

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的匹配操作ator =~而不是grep,因爲剛剛啓動grep的速度很慢。

[[ "$line" =~ (.*)000,(.*) ]] 
pointTime+=("${BASH_REMATCH[1]}") 
pointTime+=("${BASH_REMATCH[2]}") 

+0

這是完全解釋和有用的。您編輯了幾次,我實現的解決方案是'points =($(grep -Po'[0-9] +,[0-9] +'<<<「$ readData」)); pointTime =(「$ {points [@]%000,*}」); pointVal =(「$ {points [@]#*,}」)'。我沒有使用$ myfile,因爲我的實際代碼更復雜。通過您的解決方案,代碼非常快速,根本不會減速。 –

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") 
+0

我需要存儲所有數據以供進一步處理,請參閱我對原始問題的評論。即使我接受Socowi的答案,你的解決方案也看起來非常好。 +1 –