Grep භාවිතා කරමින් සිදුවීම් ගණන ගණනය කරන්න


246

grep -cගොනුවක කොපමණ වාරයක් සිදුවන්නේ දැයි සොයා ගැනීමට ප්‍රයෝජනවත් වේ, නමුත් එය එක් එක් සිදුවීම ගණනය කරන්නේ එක් පේළියකට එක් වරක් පමණි. එක් පේළියකට බහුවිධ සිදුවීම් ගණනය කරන්නේ කෙසේද?

මම වඩා අලංකාර දෙයක් සොයමි:

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

4
grepනිශ්චිතව දක්වා ඇති බව මම දනිමි , නමුත් භාවිතා කරන ඕනෑම කෙනෙකුට ackපිළිතුර සරලවම ack -ch <pattern>වේ.
කයිල් ස්ට්‍රෑන්ඩ්

Answers:


358

-oරේඛා නොසලකා හරිමින් grep ගේ ප්‍රති match ල පමණක් ප්‍රතිදානය කරයි; wcඒවා ගණන් කළ හැකිය:

grep -o 'needle' file | wc -l

මෙය 'ඉඳිකටු' හෝ 'බහුකාර්යයට' ගැලපේ.

තනි වචන පමණක් ගැලපීමට පහත විධානයන්ගෙන් එකක් භාවිතා කරන්න:

grep -ow 'needle' file | wc -l
grep -o '\bneedle\b' file | wc -l
grep -o '\<needle\>' file | wc -l

6
මේ සඳහා GNU grep (ලිනක්ස්, සිග්වින්, ෆ්‍රීබීඑස්ඩී, ඕඑස්එක්ස්) අවශ්‍ය බව සලකන්න.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

agwag මෙහි කරන්නේ කුමක්ද \bසහ \Bකරන්නේ කුමක්ද?
ගීක්

7
Ee ගීක් word b වචන සීමාවට ගැලපේ, \ B වචන සීමාවට නොගැලපේ. ඉහත පිළිතුර දෙපසම \ b භාවිතා කළේ නම් වඩාත් නිවැරදි වනු ඇත.
ලියම්

1
එක් පේළියකට සිදුවීම් ගණනක් සඳහා, grep -n විකල්පය හා uniq -c සමඟ ඒකාබද්ධ කරන්න ... grep -no '\ <needle \>' ගොනුව | uniq -c
jameswarren

@ ජේම්ස්වර්රන් uniqඉවත් කරන්නේ යාබද සමාන රේඛා පමණි, අනුපිටපත් සෑම විටම වහාම යාබදව ඇති බව ඔබට දැනටමත් විශ්වාස නැතිනම් sortපෝෂණය කිරීමට පෙර අවශ්‍ය වේ uniq.
ත්‍රිත්ව

18

ඔබට GNU grep තිබේ නම් (සෑම විටම ලිනක්ස් සහ සිග්වින් මත, ඉඳහිට වෙනත් තැනක), ඔබට ප්‍රතිදාන රේඛා ගණනය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'

POSIX මෙවලම් සමඟ පමණක්, එක් ප්‍රවේශයක් නම්, හැකි නම්, ආදානය grep වෙත යැවීමට පෙර තනි ගැලපීමක් සමඟ පේළි වලට බෙදීමයි. උදාහරණයක් ලෙස, ඔබ සම්පූර්ණ වචන සොයන්නේ නම්, පළමුව සෑම වචන නොවන අක්ෂරයක්ම නව රේඛාවක් බවට පත් කරන්න.

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

එසේ නොමැතිනම්, මෙම විශේෂිත පෙළ සැකසීම සඳහා සම්මත විධානයක් නොමැත, එබැවින් ඔබ sed (ඔබ මැසොචිස්ට්වාදියෙකු නම්) හෝ අවදි විය යුතුය.

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නව රේඛාවක් අදහස් කළ බව සලකන්න . මෙය රටා කොටසෙහි සම්මත වේ, නමුත් ආදේශන පා text යේ, අතේ ගෙන යා හැකි බව සඳහා, බැක්ස්ලෑෂ්-නව රේඛාව ආදේශ කරන්න \n.


5

මා මෙන්, ඔබට සැබවින්ම අවශ්‍ය වූයේ "දෙකම; එක් එක් හරියටම", (මෙය ඇත්ත වශයෙන්ම "එක්කෝ; දෙවරක්") එවිට එය සරල ය:

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:]]සියලුම ඇල්ෆා නොවන අක්ෂර ඇතුළත් කිරීමට.


මේ සඳහා regexp ක්ෂේත්‍ර බෙදුම්කරුවන්ට (GNU awk වැනි) සහය දක්වන awk අවශ්‍ය බව සලකන්න.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.