2012-10-09 83 views
2

的最好成績,我用的bash腳本的實驗,需要幫助解決這個:
我有一個文本文件中的以下數據:(test.txt的)慶典 - 匹配和選擇字符串

have.a.nice.day.a=42and55 
have.a.nice.day.b=0 
have.a.nice.day.c=55and67 
go.to.sleep.a=111 
go.to.sleep.b=2and122and33 
go.to.sleep.c=64 

我想要將字符串與匹配分數和分隔符(本例中爲「and」)的分數分開,並從每個分組中選出得分最高的字符串。
在這種情況下,對於組「go.to.sleep」
,對於組「have.a.nice.day」和「go.to.sleep.b」將是「have.a.nice.day.c」 所以我認爲最好的辦法是將元素分開並遞歸地賦予它們變量。像這樣:

#!/bin/bash 
names=$(cat test.txt | grep -o -P '.+(?==\d+)') 
for name in $names 
do 
    echo -n "$name"" " 
    scores=$(cat test.txt | grep -o -P '(?<='$name'=).+') 
    for scores_group in $scores 
    do 
    single_score=$(echo $scores_group | grep -o -P '\d+') 
    for score in $single_score 
    do 
     echo -n "$score"" " 
    done 
    echo 
    done 
done 

輸出將是:

have.a.nice.day.a 42 55 
have.a.nice.day.b 0 
have.a.nice.day.c 55 67 
go.to.sleep.a 111 
go.to.sleep.b 2 122 33 
go.to.sleep.c 64 

,但現在我不知道如何找到每個組的最好成績。
謝謝

+1

什麼是最終目標?效率還是學習bash? –

+0

最終目標是學習bash – buntuser

回答

3

所以,你的實際問題,我認爲,你如何把你已經標記爲「輸出」的「輸入文本」,並找到最高數量的行?

假設你的輸出輸入,我會使用awk做到這一點:

$ awk '{name=$1; item=$1; sub(/\.[^.]+$/,"",name); sub(/.*\./,"",item); for (i=2; i<=NF; i++) {if($i>highest[name]){highest[name]=$i;which[name]=item}}} END{for(name in highest){printf("%s = %s = %s\n",name,which[name],highest[name])}}' input.txt 
go.to.sleep = b = 122 
have.a.nice.day = c = 67 

或者,爲了解釋爆發了:

{ 

    # Get the parts of the first field... 
    name=$1; sub(/\.[^.]+$/,"",name); 
    item=$1; sub(/.*\./,"",item); 

    # Walk through the scores, record the highest in an array 
    for (i=2; i<=NF; i++) { 
    if ($i>highest[name]) { 
     highest[name]=$i; 
     which[name]=item; 
    } 
    } 
} 

# Now, step through the resultant array 
END { 
    for (name in highest) { 
    printf("%s = %s = %s\n",name,which[name],highest[name]); 
    } 
} 

請問這個怎麼辦?還是你真的想要在純粹的bash中實現這個?如果是這樣,上面的awk可以用下面的bash表示:

#!/bin/bash 

declare -A highest 
declare -A which 

while read word scores; do 
    name=${word%.*} 
    item=${word##*.} 
    set -- $scores 
    while [[ -n "$1" ]]; do 
     if [[ $1 -gt highest[$name] ]]; then 
      highest[$name]=$1 
      which[$name]=$item 
     fi 
     shift 
    done 
done < input.txt 

for name in "${!highest[@]}"; do 
    printf "%s = %s = %s\n" "$name" "${which[$name]}" "${highest[$name]}" 
done 
+0

這會得到我的投票。我仍然最喜歡'awk' :-) – Steve

+0

謝謝ghoti,我正在研究你的答案.. – buntuser

+0

甚至經過幾個小時的閱讀bash手冊和例子,我仍然在這裏輸了.. – buntuser