গ্রেপ ব্যবহার করে ঘটনার মোট সংখ্যা গণনা করুন


215

grep -cকোনও ফাইলের মধ্যে স্ট্রিং কতবার ঘটে তা সন্ধানের জন্য দরকারী তবে এটি প্রতি লাইনে একবারে প্রতিটি ঘটনা গণনা করে। প্রতি লাইনে একাধিক উপস্থিতি গণনা কিভাবে?

আমি এর চেয়ে আরও মার্জিত কিছু খুঁজছি:

perl -e '$_ = <>; print scalar ( () = m/needle/g ), "\n"'

4
আমি জানি grepসুনির্দিষ্ট, তবে যে কেউ ব্যবহার করছেন ack, উত্তরটি সহজ ack -ch <pattern>
কাইল স্ট্র্যান্ড

উত্তর:


302

গ্রেপ এর -oলাইন উপেক্ষা করে কেবল ম্যাচগুলিকে আউটপুট দেয়; wcতাদের গণনা করতে পারেন:

grep -o 'needle' file | wc -l

এটি 'সুই' বা 'মাল্টিনেডেল' এর সাথেও মিলবে।
শুধুমাত্র একক শব্দ:

grep -o '\bneedle\B' file | wc -l
# or:
grep -o '\<needle\>' file | wc -l

6
মনে রাখবেন এর জন্য জিএনইউ গ্রেপ (লিনাক্স, সাইগউইন, ফ্রিবিএসডি, ওএসএক্স) প্রয়োজন।
গিলস

@ ওয়াগ এখানে কি যাদু করে \bএবং \Bকি করে?
গীক

6
@ গীক \ বি একটি শব্দের সীমানা মেলে, \ বি শব্দের সীমানা নয় উপরের উত্তরটি আরও সঠিক হবে যদি এটি উভয় প্রান্তে \ b ব্যবহার করে।
লিয়াম

1
প্রতি লাইনে সংখ্যার সংখ্যার জন্য, গ্রেপ-এন বিকল্প এবং ইউনিক-সি ... এর সাথে একত্রিত করুন ... গ্রেপ -না 'need <সুই \>' ফাইল | uniq -c
jameswarren

@ জেমসওয়ারেন uniqকেবল সংলগ্ন অভিন্ন লাইনগুলি সরিয়ে ফেলবে, আপনি যদি sortআগে uniqথেকেই নিশ্চিত হন না যে নকলগুলি সর্বদা তত্ক্ষণাত সংলগ্ন হবে তবে আপনার খাওয়ানোর আগে আপনাকে খাওয়াতে হবে।
ট্রিপলি

16

আপনি গনুহ, grep (সবসময় Linux এবং Cygwin, মাঝে মাঝে অন্যত্র দিকে) থাকে, তাহলে আপনি পারবেন না থেকে আউটপুট লাইন গণনাgrep -o : grep -o needle | wc -l

পার্ল সঙ্গে, এখানে কয়েকটি উপায় (পরও এটা আমি পুলিশের চেয়ে বেশি মার্জিত এটি হয় সংশোধন করা হয়েছে )।

perl -lne 'END {print $c} map ++$c, /needle/g'
perl -lne 'END {print $c} $c += s/needle//g'
perl -lne 'END {print $c} ++$c while /needle/g'

কেবল পসিক্স সরঞ্জামের সাহায্যে একটি পদ্ধতির, যদি সম্ভব হয় তবে গ্রেপতে যাওয়ার আগে ইনপুটটিকে একক ম্যাচের সাথে লাইনগুলিতে ভাগ করে নেওয়া হয়। উদাহরণস্বরূপ, আপনি যদি পুরো শব্দটি সন্ধান করছেন তবে প্রথমে প্রতিটি অ-শব্দ অক্ষরকে একটি নতুন লাইনে পরিণত করুন।

# equivalent to grep -ow 'needle' | wc -l
tr -c '[:alnum:]' '[\n*]' | grep -c '^needle$'

অন্যথায়, পাঠ্য প্রক্রিয়াজাতকরণের এই বিটটি করার জন্য কোনও স্ট্যান্ডার্ড কমান্ড নেই, সুতরাং আপনাকে সেডে ফিরে যেতে হবে (আপনি যদি কোনও মাসোশিস্ট হন) বা অজস্র।

awk '{while (match($0, /set/)) {++c; $0=substr($0, RSTART+RLENGTH)}}
     END {print c}'
sed -n -e 's/set/\n&\n/g' -e 's/^/\n/' -e 's/$/\n/' \
       -e 's/\n[^\n]*\n/\n/g' -e 's/^\n//' -e 's/\n$//' \
       -e '/./p' | wc -l

এখানে একটি সহজ সমাধান sedএবং এটি ব্যবহার করা হয়েছে grep, যা স্ট্রিং বা এমনকি বইয়ের নিয়মিত প্রকাশের জন্য কাজ করে তবে অ্যাঙ্কার্ড প্যাটার্নগুলির সাথে কয়েকটি কোণায় ব্যর্থ হয় (যেমন এটি দুটি ক্ষেত্রে ^needleবা এর দুটি সন্ধান \bneedleকরে needleneedle)।

sed 's/needle/\n&\n/g' | grep -cx 'needle'

নোট করুন যে উপরের সিড বিকল্পগুলিতে আমি \nএকটি নতুন লাইনটি বোঝাতে চাইছিলাম। এটি প্যাটার্ন অংশে আদর্শ, তবে প্রতিস্থাপন পাঠ্যে, বহনযোগ্যতার জন্য, ব্যাকস্ল্যাশ-নিউলাইন বিকল্পের জন্য \n


4

যদি আমার মতো আপনিও "উভয়ই; প্রতিটি একেবারে একবার" চেয়েছিলেন , (এটি আসলে "হয়; দু'বার") তবে এটি সহজ:

grep -E "thing1|thing2" -c

এবং আউটপুট জন্য পরীক্ষা করুন 2

এই পদ্ধতির সুবিধা (যদি ঠিক একবার হয় আপনি যা চান তা) এটি সহজে আইশ করে।


আমি নিশ্চিত না যে আপনি এটি একবারে কেবল প্রদর্শিত হচ্ছে তা পরীক্ষা করছেন? আপনি যেদিকে যা খুঁজছেন তা হ'ল অন্তত একবার এই শব্দগুলির মধ্যে একটির উপস্থিতি রয়েছে।
স্টিভ গোর

3

জাজ এবং needleফিল্ড বিভাজক হিসাবে আরও একটি সমাধান :

awk -F'^needle | needle | needle$' '{c+=NF-1}END{print c}'

যদি আপনি needleবিরামচিহ্ন অনুসরণ করে মেলাতে চান তবে ক্ষেত্র বিভাজককে সেই অনুযায়ী পরিবর্তন করুন

awk -F'^needle[ ,.?]|[ ,.?]needle[ ,.?]|[ ,.?]needle$' '{c+=NF-1}END{print c}'

বা ক্লাসটি ব্যবহার করুন: [^[:alnum:]]সমস্ত অ্যালफा অক্ষরকে অন্তর্ভুক্ত করতে।


নোট করুন যে এর জন্য এমন একটি জঞ্জাল দরকার যা পুনর্নির্মাণ ক্ষেত্র বিভাজককে সমর্থন করে (যেমন জিএনইউ অ্যাডক)।
গিলস

1

আপনার উদাহরণটি কেবল প্রতি-লাইনে সংখ্যার প্রিন্ট করে এবং ফাইলের মোটটি নয়। যদি আপনি এটি চান তবে এর মতো কিছু কাজ করতে পারে:

perl -nle '$c+=scalar(()=m/needle/g);END{print $c}' 

আপনি ঠিক বলেছেন - আমার উদাহরণটি কেবল প্রথম লাইনে উপস্থিতি গণনা করে।

1

এটি আমার খাঁটি বাশ সমাধান

#!/bin/bash

B=$(for i in $(cat /tmp/a | sort -u); do
echo "$(grep $i /tmp/a | wc -l) $i"
done)

echo "$B" | sort --reverse
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.