2011-08-24 8 views
5

मैं समय की संख्या को खोजने के लिए एक शब्द भी एक पाठ फ़ाइल में होता है जैसे लिनक्स में हममुझे टेक्स्ट फ़ाइल में एकाधिक शब्दों की गिनती कैसे मिलती है?

cat filename|grep -c tom 

उपयोग कर सकते हैं मेरे सवाल है मैं "टॉम" और "जो की तरह कई शब्दों की गिनती कैसे मिल रहा है कर रहा हूँ "एक पाठ फ़ाइल में।

+0

grep लाइनों की गणना करता है, शब्द नहीं। क्या उस पर 'टॉमटॉम' वाली रेखा एक या दो के रूप में गिना जाता है? – tchrist

+0

आप वास्तव में क्या चाहते हैं? आपके द्वारा निर्दिष्ट प्रत्येक शब्द के अनुसार एकाधिक मायने रखता है? आपके द्वारा निर्दिष्ट सभी शब्दों के लिए गणना का योग? "शब्द" क्या है - जैसा कि पहले से ही वर्णित है, आपका उदाहरण उन पंक्तियों की संख्या की गणना करता है जो regexp से मेल खाते हैं, शब्दों की संख्या नहीं। – GreyCat

उत्तर

3

जब से तुम एक जोड़ी के नाम है, नियमित अभिव्यक्ति पर जाने के लिए रास्ता नहीं है यह वाला। पहले मैंने सोचा था कि यह जो या टॉम की नियमित अभिव्यक्ति पर सिर्फ एक grep गिनती के रूप में सरल था, लेकिन यह झगड़ा था कि यह उस परिदृश्य के लिए जिम्मेदार नहीं था जहां टॉम और जो एक ही रेखा पर हैं (या उस मामले के लिए टॉम और टॉम) ।

परीक्षण।txt:

tom is really really cool! joe for the win! 
tom is actually lame. 


$ grep -c '\<\(tom\|joe\)\>' test.txt 
2 

आप test.txt फ़ाइल से देख सकते हैं, 2 गलत जवाब है, तो हम नाम एक ही लाइन पर किया जा रहा है के लिए खाते की जरूरत है।

मैंने फिर grep -o का उपयोग केवल एक मिलान रेखा का हिस्सा दिखाने के लिए किया था जो पैटर्न से मेल खाता है जहां उसने फ़ाइल में टॉम या जो के सही पैटर्न मैचों को दिया था। फिर मैंने लाइन गिनती के लिए परिणामों को डब्ल्यूसी में लाइनों की संख्या में पाइप कर दिया।

$ grep -o '\(joe\|tom\)' test.txt|wc -l 
     3 

3 ... सही उत्तर! आशा है कि इस मदद करता है

+2

'टॉमटॉम' के बारे में क्या? – tchrist

+0

मैंने नियमित अभिव्यक्ति को टॉमटॉम के मामले को संभालने के लिए थोड़ा सा संशोधित किया। अच्छा परीक्षण मामला ... इसे इंगित करने के लिए धन्यवाद। –

+0

वास्तव में हार्ड टेस्ट केस में मूल शब्दों पर ओवरलैपिंग मैचों शामिल होंगे। :) उदाहरण के लिए, यदि आप जिन शब्दों की गिनती चाहते थे वे 'इलाज', 'कोर', 'रेली', 'लीसिस', 'द्वीप', 'भूमि' और 'पकवान' थे, तो आपको 2 हिट मिलेगी 'असुरक्षित' और 'अपमानजनक' जैसी चीजें और 'द्वीपसमूह' और 'कोरलीसिस' जैसी चीजों पर 3 हिट। एक भद्दा दृष्टिकोण उनको केवल एक ही के रूप में गिना जाएगा। यह एक regex के साथ मजेदार नहीं है, लेकिन उनमें से एक के साथ बहुत आसान है, एक प्रति शब्द। – tchrist

2

ठीक है, इसलिए सबसे पहले शब्दों में फ़ाइल विभाजित है, तो sort और uniq:

tr -cs '[:alnum:]' '\n' < testdata | sort | uniq -c 

आप uniq का उपयोग करें:

sort filename | uniq -c 

+0

शब्द, ** नहीं ** रेखाएं। –

+1

हूप्स। अगली बार, मैं इस सवाल को सही तरीके से कैसे पढ़ूं? * फेसपाल्म * – carlpett

+0

यह (शब्दों में विभाजित, चयन, गिनती) मेरा विकल्प भी होता। जब उन चीजों को प्रतिस्थापित करना जो 'alnum:' to \ n' नहीं हैं, तो आपको भाषा अंतरों की देखभाल करने की आवश्यकता हो सकती है, जैसे कि बिल्ली कैस्टिलियन/*। txt | टी ए-जेड ए-जेड | tr -cs '[a-záóúíéñ]' '\ n' | सॉर्ट | uniq -c | sort -n' – mariotomo

1

awk का उपयोग करें:

{for (i=1;i<=NF;i++) 
    count[$i]++ 
} 
END { 
    for (i in count) 
     print count[i], i 
} 

यह इनपुट के लिए एक पूर्ण शब्द आवृत्ति गणना उत्पन्न करेगा। grep को पाइप यद्यपि उत्पादन वांछित क्षेत्रों

awk -f w.awk input | grep -E 'tom|joe' 

Btw, आप अपने उदाहरण में cat की जरूरत नहीं है पाने के लिए, ज्यादातर कार्यक्रमों में कार्य करता है कि के रूप में फिल्टर एक पैरामीटर के रूप में फ़ाइल नाम ले सकते हैं; इसलिए यह

grep -c tom filename 

उपयोग करने के लिए यदि नहीं, तो इस बात की प्रबल संभावना है बेहतर है कि लोगों को Useless Use of Cat Award फेंकने आप ;-) पर

+0

"फ़िल्टर के रूप में कार्य करने वाले अधिकांश प्रोग्राम फ़ाइल नाम को पैरामीटर के रूप में ले सकते हैं" ... और जब भी वे नहीं करते हैं, तब भी आप इनपुट रीडायरेक्शन (जैसे 'grep -c tom

+0

'grep -c' शब्दों की तलाश नहीं करता है, इसलिए आपको इसकी खोज करनी है। –

0

यहाँ एक है शुरू कर देंगे:

cat txt | tr -s '[:punct:][:space:][:blank:]'| tr '[:punct:][:space:][:blank:]' '\n\n\n' | tr -s '\n' | sort | uniq -c 

अद्यतन

एक शेल स्क्रिप्ट समाधान:

#!/bin/bash 

file_name="$2" 
string="$1" 

if [ $# -ne 2 ] 
    then 
    echo "Usage: $0 <pattern to search> <file_name>" 
    exit 1 
fi 

if [ ! -f "$file_name" ] 
then 
    echo "file \"$file_name\" does not exist, or is not a regular file" 
    exit 2 
fi 

line_no_list=("") 
curr_line_indx=1 
line_no_indx=0 
total_occurance=0 

# line_no_list contains loc k the line number loc k+1 the number 
# of times the string occur at that line 
while read line 
do 
    flag=0 
    while [[ "$line" == *$string* ]] 
    do 
    flag=1 
    line_no_list[line_no_indx]=$curr_line_indx 
    line_no_list[line_no_indx+1]=$((line_no_list[line_no_indx+1]+1)) 
    total_occurance=$((total_occurance+1)) 
# remove the pattern "$string" with a null" and recheck 
    line=${line/"$string"/} 
    done 
# if we have entered the while loop then increment the 
# line index to access the next array pos in the next 
# iteration 
    if ((flag == 1)) 
    then 
    line_no_indx=$((line_no_indx+2)) 
    fi 
    curr_line_indx=$((curr_line_indx+1)) 
done < "$file_name" 


echo -e "\nThe string \"$string\" occurs \"$total_occurance\" times" 
echo -e "The string \"$string\" occurs in \"$((line_no_indx/2))\" lines" 
echo "[Occurence # : Line Number : Nos of Occurance in this line]: " 

for ((i=0; i<line_no_indx; i=i+2)) 
do 
    echo "$((i/2+1)) : ${line_no_list[i]} : ${line_no_list[i+1]} " 
done 

echo 
0
  1. नमूना आप दिया करता नहीं शब्द "टॉम" के लिए खोज। यह "परमाणु" और "नीचे" और कई अन्य लोगों की गणना करेगा।
  2. Grep नियमित अभिव्यक्ति के लिए खोज करता है। नियमित अभिव्यक्ति है कि शब्द "टॉम" या "जो" से मेल खाता

    \<\(tom\|joe\)\> 
    
0

आप regexp कर सकता है,

cat filename |tr ' ' '\n' |grep -c -e "\(joe\|tom\)" 
+0

आपका समाधान भी उसी लाइन पर जो और टॉम के लिए खाता है। अच्छा! –

+0

@ ट्रेविस: हालांकि, यह गलती से केवल एक बार 'टॉमटॉम' की गणना करता है, भले ही मेरे दादाजी भी देख सकें कि दो 'टॉम' मौजूद हैं। – tchrist

0

मैं पूरी तरह से भूल गया के बारे में ग्रेप -f:

cat filename | grep -fc names 

AWK समाधान:

नाम मान लिया जाये कि एक फ़ाइल में names कहा जाता है:

cat filename | awk 'NR==FNR {h[NR] = $1;ct[i] = 0; cnt=NR} NR !=FNR {for(i=1;i<=cnt;++i) if(match($0,h[i])!=0) ++ct[i] } END {for(i in h) print h[i], ct[i]}' names - 

ध्यान रखें कि आपके मूल grep शब्दों की खोज नहीं करता है। जैसे

$ echo tomorrow | grep -c tom 
1 

आप grep -w

0
gawk -vRS='[^[:alpha:]]+' '{print}' | grep -c '^(tom|joe|bob|sue)$' 

जरूरत gawk कार्यक्रम कुछ भी गैर वर्णमाला के लिए रिकॉर्ड विभाजक सेट है, तो हर शब्द एक अलग लाइन पर खत्म हो जाएगा। फिर grep उन पंक्तियों की गणना करता है जो आपके इच्छित शब्दों में से एक से मेल खाते हैं।

हम गॉक का उपयोग करते हैं क्योंकि POSIX awk regex रिकॉर्ड विभाजक को अनुमति नहीं देता है।

संक्षिप्तता के लिए, आप 1 साथ '{print}' जगह ले सकता है - किसी भी तरह से, यह एक Awk कार्यक्रम है कि बस सभी इनपुट रिकॉर्ड बाहर प्रिंट है

(" 1 सच है यह है तो डिफ़ॉल्ट क्रिया है, जो {print} है??।")
0

सभी लाइनों

echo "tom is really really cool! joe for the win! 
tom is actually lame." | akw '{i+=gsub(/tom|joe/,"")} END {print i}' 
3 

यह सभी हिट लगाने के लिए 2 हिट के रूप में "टॉम टॉम" में रखा जाएगा।

संबंधित मुद्दे