2017-12-18 64 views
6

में उनके मानों का योग मैं तार (stdin) अगले तरह की एक सूची है:क्रमबद्ध कुंजी और बैश

1 pineapples 
28 apples 
16 oranges 
8 apples 
2 apples 
2 oranges 
56 pineapples 

वहाँ एक देशी तरीका (जैसे sort & uniq -c) जिसके साथ मैं विलय और उनकी तरह योग कर सकता है इस:

38 apples 
18 oranges 
57 pineapples 

sort |uniq -c की तरह करते हैं, लेकिन नहीं घटनाओं संख्या के लिए ही है?

उत्तर

11

इस एक का प्रयास करें:

awk '{a[$2] += $1} END{for (i in a) print a[i], i}' < in.txt 

उत्पादन

38 apples 
57 pineapples 
18 oranges 
+3

जब नौकरी के लिए सही उपकरण है, तो यह वास्तव में नौकरी के लिए सही उपकरण है। – zzxyz

+0

प्यार बहुत अच्छा है, हालांकि इसे अच्छी तरह से नहीं पता है, बस यह सुनिश्चित था कि यह यहां फिट होगा, इसलिए सही टैग डालें :) –

+0

यह सुरुचिपूर्ण है, लेकिन ध्यान दें कि आउटपुट * सॉर्ट नहीं किया गया है *। यह सवाल से स्पष्ट नहीं है कि यह एक वास्तविक आवश्यकता है, लेकिन केवल कुछ पता होना चाहिए। एक साइड नोट के रूप में, जीएनयू 'awk' * * परिभाषित (क्रमबद्ध) तरीके से लूप के लिए ट्रैवर्स सरणी कर सकते हैं, 'PROCINFO [" sorted_in "]' के माध्यम से नियंत्रित (इस मामले में, कोई सेट करेगा: 'PROCINFO [" sorted_in " ] = "@val_str_asc" ')। – randomir

0

Awk इस काम के लिए सही उपकरण है। हालांकि यहां एक वैकल्पिक संस्करण है जिसमें associative arrays है जो अजीब से परिचित नहीं हैं और जिनके पास बैश संस्करण> = 4.0 है। यह फ़ाइल की प्रत्येक पंक्ति को फलों को पढ़ता है और कुंजी के रूप में दूसरे कॉलम का उपयोग करके संख्याओं को संग्रहीत करता है।

declare -A Sumarray 
while IFS=" " read num thing 
do 
    if [[ -v Sumarray[$thing] ]] 
    then 
    Sumarray[$thing]=$((${Sumarray[$thing]} + $num)) 
    else 
    Sumarray[$thing]=$num 
    fi 
done < Fruits 

$ for K in "${!Sumarray[@]}"; do echo ${Sumarray[$K]} $K ; done 
38 apples 
57 pineapples 
18 oranges 
+1

जो लोग अजीब से परिचित नहीं हैं उन्हें अजीब सीखना चाहिए ताकि वे आसानी से, कुशलतापूर्वक, पोर्टेबल, मजबूती से इत्यादि जैसी चीजें कर सकें .. एक खोल फाइलों और प्रक्रियाओं में हेरफेर करने के लिए है, पाठ में हेरफेर करने के लिए आपको उस उपकरण का उपयोग करना चाहिए जो लोग शैवाल का आविष्कार करते हैं पाठ में हेरफेर करने के लिए आविष्कार - अजीब .. –

4

GNU datamash के साथ: इनपुट क्षेत्र सीमांकक के लिए

$ <file datamash -Wst' ' -g2 sum 1 
apples 38 
oranges 18 
pineapples 57 

(-W उपयोग खाली स्थान के, -t' ' उत्पादन फ़ील्ड परिसीमक, -s तरह इनपुट के लिए एक अंतरिक्ष, स्तंभ 2 से -g2 समूह, स्तंभ से sum 1 राशि मूल्यों का उपयोग प्रत्येक समूह में 1।)

यहां कोई बड़ा विजेता नहीं है (awk से अधिक), लेकिन यह वास्तव में थोड़ा और जटिल पर चमकता है सांख्यिकीय संचालन (उदा। गणना समूह मध्य, भिन्नता, skewness, आदि)।

प्रश्न में दिए गए (कि अगर मायने रखती है) स्वरूप पाने के लिए, हम स्वयं उत्पादन क्षेत्रों के क्रम को उल्टा करने के लिए क्योंकि datamash हमेशा आउटपुट की जरूरत वर्गीकृत किया-से पहले कॉलम:

$ <file datamash -Wst' ' -g2 sum 1 | datamash -Wt' ' reverse 
38 apples 
18 oranges 
57 pineapples 
0

संक्षेप मूल्यों और छँटाईawk का उपयोग कर उत्पादन:

awk '{ 
    items[$2]+=$1 
} 
END { 
    asorti(items, sorted) 
    for(i in sorted) 
     print items[sorted[i]] " " sorted[i] 
}' input_file 

का उपयोग केवल bash:

declare -A items=() 

while read -r num item; do 
    ((items[$item] += num)) 
done < input_file 

sorted=() 
while IFS= read -r -d '' item; do 
    sorted+=("$item") 
done < <(printf '%s\0' "${!items[@]}" | sort -z) 

for index in "${sorted[@]}"; do 
    echo "${items[$index]} $index" 
done 
संबंधित मुद्दे