पैटर्न मैच से पहले / बाद में कुल पंक्तियों की गिनती करें


9

मैं आईपी पते की एक लंबी सूची बना रहा हूं, जो क्रम में नहीं हैं। मुझे यह पता लगाने की आवश्यकता है कि किसी विशेष आईपी पते से पहले / बाद में कितने आईपी पते हैं। इसे कैसे प्राप्त किया जा सकता है?


क्या आपके पास IP डुप्लिकेट है?
कोउंगलम

नहीं। सभी आईपी पते अद्वितीय हैं।
मंदर शिंदे

IP पते के लिए माध्य से पहले / बाद में क्या करता है? विशेष रूप से, क्या आपके पास IPv4 और IPv6 दोनों पते हैं? वे कैसे तुलना करते हैं?
vinc17

क्या आपको सॉर्ट की गई फ़ाइल की आवश्यकता है?
क्यूंगलोम

2
@ vinc17 - फ़ाइल में केवल IP पते (IPv4) हैं, कोई अन्य डेटा शामिल नहीं है। यदि कुल 1000 आईपी पते हैं, और मैच 300 वें स्थान पर पाया जाता है, तो इसका मतलब है कि मैच से पहले 299 लाइनें और मैच के बाद 700 लाइनें हैं।
मंदर शिंदे

जवाबों:


8

मैच से पहले और बाद में लाइनों की संख्या, जिसमें मैच भी शामिल है (यानी अगर आपको मैच को बाहर करना है तो परिणाम से 1 को घटाना होगा):

sed -n '0,/pattern/p' file | wc -l
sed -n '/pattern/,$p' file | wc -l

लेकिन यह विशेष रूप से आईपी पते के साथ कुछ नहीं करना है।


4

शायद सबसे आसान है,

sed -n '/pattern/{=; q;}' file

त्रुटि इंगित करने के लिए @JoshepR को धन्यवाद


यह सिर्फ उस लाइन नंबर को प्रिंट करता है जिस पर पैटर्न हुआ था।
जोसेफ आर।

@JosephR। - नहीं, यह हर लाइन नंबर को प्रिंट करता है , जिस पर हर मैच होता है।
चाटुकार

@mikeserv मुझे पता है लेकिन ओ पी निर्दिष्ट कि IP पते अद्वितीय हैं। ओपी यह भी नहीं चाहता है कि मैच (तों) कहां हुआ; वे पैटर्न के आने से पहले लाइनों की संख्या और उसके बाद की लाइनों की संख्या चाहते हैं।
यूसुफ आर।

@ जोसेफ - उन काउंट्स पर पहुंचने का सबसे तेज तरीका लाइन नंबरों को टैली करना है - मैं इसे सीधे dcअपने आप को पाइप करूंगा, शायद।
चाटुकार

@mikeserv मैं यह तर्क नहीं दे रहा हूं कि इस उत्तर से मिली जानकारी उपयोगी नहीं है, मैं सिर्फ यह कह रहा हूं कि यह कोड अपने आप ही ऐसा नहीं करता है जो ओपी चाहता है।
जोसेफ आर।

3

मैंने यह दो तरीके से किया, हालांकि मुझे लगता है कि मुझे यह सबसे अच्छा लगता है:

: $(( afterl=( lastl=$(wc -l <~/file) ) - 2 -
  $(( beforel=( matchl=$(sed -n "/$IP/{=;q;}" <~/file) ) - 1
)) ))
for n in last match afters befores
do  printf '%s line%s :\t%d\n' \
        "${n%s}" "${n##*[!s]}" $((${n%s}l))
done

वर्तमान शेल चर के रूप में उन सभी को बचाता है - और आउटपुट के लिए बाद में लूप के लिए उनका मूल्यांकन करता है। यह फ़ाइल में कुल लाइनों को गिनता है wcऔर इसके साथ पहली मिलान वाली पंक्ति संख्या प्राप्त करता है sed

इसका आउटपुट:

last line :     1000
match line :    200
after lines :   799
before lines :  199

मैंने भी किया:

sed -n "/$IP/=;\$=" ~/file |  
tr \\n \  | { 
IFS=' ' read ml ll 
printf '%s line%s:\t%d\n' \
    last '' $((ll=${ll##* }))
    match '' $ml \
    after s "$((al=ll-ml-1)) \ 
    before s $((bl=ml-1))
}

sedकेवल मिलान और अंतिम पंक्ति संख्या प्रिंट करता है, फिर trहस्तक्षेप करने वाली \newlines का अनुवाद करता है, और में और अन्य सभी में readसे पहले sedपरिणाम पढ़ता है । संभावित कई मैच के मामलों को सभी के द्वारा अलग किया जाता है, लेकिन अंतिम परिणाम के अंतिम परिणाम के बाद इसे फिर से सेट करते समय।$ml$ll$ll

इसका आउटपुट:

last line :     1000
match line :    200
after lines :   799
before lines :  199

निम्न तरीके से उत्पन्न फ़ाइल पर दोनों तरीकों का परीक्षण किया गया था:

IP='some string for which I seek' 
for count in 1 2 3 4 5 
do  printf '%.199d%s\n' 0 "$IP" 
done | tr 0 \\n >~/file 

यह लाइन नंबर द्वारा होता है:

  1. खोज स्ट्रिंग सेट करता है
  2. यह सुनिश्चित करने के लिए पांच बार लूप होता है कि कई मैच होंगे
  3. 199 शून्य को प्रिंट करता है और "$IP"फिर एक \newline
  4. पाइप आउटपुट tr- जो शून्य को \newlines में तब अनुवाद करता है~/file

2

यहाँ थोड़ा पर्ल कोड है जो इसे करता है:

perl -ne '
     if(1 .. /192\.168\.1\.1/) { $before++ }
     else                      { $after++  }
     $before--; # The matching line was counted
     END{print "Before: $before, After: $after\n"}' your_file

यह आईपी युक्त लाइन से पहले और बाद में लाइनों की कुल संख्या को गिनता है 192.168.1.1। अपने इच्छित आईपी से बदलें।

बाश के अलावा और कुछ का उपयोग करना:

before=0
match=0
after=0
while read line;do
    if [ "$line" = 192.168.1.1 ];then
        match=1
    elif [ $match -eq 0 ];then
        before=$(($before+1))
    else
        after=$(($after + 1))
    fi
done < your_file
printf "Before: %d, After: %d\n" "$before" "$after"

BASH को प्राथमिकता दी जाती है।
मंदर शिंदे

2
@ जोसेफ आर .: आप $.एक काउंटर के बजाय उपयोग क्यों नहीं करते ?
क्यूंग्लम

@Gnouc मैं निश्चित रूप से कर सकता था। मुझे लगता है कि सिर्फ इस की स्थापना की तुलना में अधिक पठनीय है $afterकरने के लिए $. - $before
यूसुफ आर।

नहीं, मेरा मतलब है: मिलान किया है, प्रिंट $. - 1, बचाने $.के लिए $tmp। अंत प्रिंट $. - $tmp। इसलिए हमें पहले और बाद दोनों के लिए काउंटर की आवश्यकता नहीं है। बेशक यह आपकी तुलना में कम पठनीय है।
क्यूंगलोम

@MandarShinde कृपया संपादन देखें। मैंने एक शुद्ध बैश उत्तर जोड़ा।
जोसेफ आर।

2

मैं निम्नलिखित आदेशों की कोशिश कर रहा था, जो थोड़े जटिल हैं, लेकिन सटीक परिणाम देंगे:

उपरांत:

a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l

इससे पहले:

echo "`cat -n file | grep <Pattern> | awk '{print $1}'`-1" | bc -l

2

awkअंतिम मैच से पहले और बाद में लाइनों की एक समाधान रिपोर्टिंग संख्या

awk '/192\.168\.1\.1/{x=NR};{y=NR} END{printf "before-%d, after-%d\n" , x-1, y-x}'  file

1

Grepएक ऐसी विशेषता है जो किसी विशेष पैटर्न के मिलने की संख्या को गिन सकती है। यदि आप -cकमांड का उपयोग करते हैं जो ऐसा करेगा। साथ -cऔर -vआदेश, इस की गणना होती है इस कितनी बार एक खास पैटर्न से मेल नहीं खाता

उदाहरण:

grep -c -v <pattern> file

तो अगर आप कुछ इस तरह की कोशिश करते हैं:

grep -c -v 192.168.x.x file.log वह काम करना चाहिए।


यह लक्ष्य IP की घटनाओं की संख्या को गिनाता है। यह वह नहीं है जो ओपी ने मांगा था।
जोसेफ आर।

मैंने अभी इसे संपादित किया है, अगर वह किसी विशेष आईपी से पहले और बाद में अन्य सभी आईपी को गिनने के लिए कह रहा है, तो संपादन उसके लिए काम करना चाहिए।
रेकायो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.