Zählen Sie die Gesamtzahl der Zeilen vor / nach einer Musterübereinstimmung

9

Ich habe eine lange Liste von IP-Adressen, die nicht der Reihe nach sind. Ich muss herausfinden, wie viele IP-Adressen vor / nach einer bestimmten IP-Adresse vorhanden sind. Wie kann ich das erreichen?

Mandar Shinde
quelle
Haben Sie IP dupliziert?
Cuonglm
Nein. Alle IP-Adressen sind eindeutig.
Mandar Shinde
Was bedeutet Vorher / Nachher für eine IP-Adresse? Haben Sie insbesondere sowohl IPv4- als auch IPv6-Adressen? Wie vergleichen sie?
vinc17
Benötigen Sie die Datei sortiert?
Cuonglm
2
@ vinc17 - Datei enthält nur IP-Adressen (IPv4), keine anderen Daten sind enthalten. Wenn insgesamt 1000 IP-Adressen vorhanden sind und die Übereinstimmung an der 300. Stelle gefunden wird, bedeutet dies, dass 299 Zeilen vor der Übereinstimmung und 700 Zeilen nach der Übereinstimmung vorhanden sind.
Mandar Shinde

Antworten:

8

Anzahl der Zeilen vor und nach einer Übereinstimmung, einschließlich der Übereinstimmung (dh Sie müssen 1 vom Ergebnis abziehen, wenn Sie die Übereinstimmung ausschließen möchten):

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

Dies hat jedoch insbesondere nichts mit IP-Adressen zu tun.

vinc17
quelle
4

Vielleicht ist das einfachste,

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

Vielen Dank an @JoshepR für den Hinweis auf den Fehler

jpmuc
quelle
Dies gibt nur die Zeilennummer aus, auf der das Muster aufgetreten ist.
Joseph R.
@ JosephR. - Nein, es wird jede Zeilennummer gedruckt , auf der jede Übereinstimmung auftritt.
Mikeserv
@mikeserv Ich weiß, aber das OP hat angegeben, dass IP-Adressen eindeutig sind. Das OP möchte auch nicht die Zeilennummer, in der die Übereinstimmung (en) aufgetreten sind. Sie möchten die Anzahl der Zeilen vor dem Auftreten des Musters und die Anzahl der Zeilen danach.
Joseph R.
@JosephR - der schnellste Weg, um zu diesen Zählungen zu gelangen, besteht darin, die Zeilennummern zu zählen - ich würde dies dcwahrscheinlich direkt an mich selbst weiterleiten .
Mikeserv
@mikeserv Ich behaupte nicht, dass die Informationen aus dieser Antwort nicht nützlich sind, ich sage nur, dass dieser Code alleine nicht das tut, was das OP will.
Joseph R.
3

Ich habe das auf zwei Arten gemacht, obwohl ich denke, dass mir das am besten gefällt:

: $(( 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

Das speichert all diese als aktuelle Shell-Variablen - und wertet sie anschließend in der for-Schleife für die Ausgabe aus. Es zählt die Gesamtzahl der Zeilen in der Datei mit wcund erhält die erste übereinstimmende Zeilennummer mit sed.

Seine Ausgabe:

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

Ich habe auch getan:

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))
}

seddruckt nur übereinstimmende und letzte Zeilennummern und trübersetzt dann die dazwischen liegenden \nZeilen inund readliest die ersten sedErgebnisse in $mlund alle anderen in $ll. Mögliche Fälle mit mehreren Übereinstimmungen werden behandelt, indem alle bis auf das letzte Ergebnis aus der $llErweiterung entfernt werden, wenn sie später erneut festgelegt werden.

Seine Ausgabe:

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

Beide Methoden wurden an der auf folgende Weise generierten Datei getestet:

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 

Nach Zeilennummer:

  1. Legt die Suchzeichenfolge fest
  2. Schleifen fünf Mal, um sicherzustellen, dass es mehrere Übereinstimmungen gibt
  3. druckt 199 Nullen und "$IP"dann eine \nEwline
  4. pipes output to tr- übersetzt Nullen in \newlines und dann in~/file
mikeserv
quelle
2

Hier ist ein bisschen Perl-Code, der das macht:

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

Dies zählt die Gesamtzahl der Zeilen vor und nach der Zeile, die die IP enthält 192.168.1.1. Ersetzen Sie durch Ihre gewünschte IP.

Verwenden Sie nur Bash:

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"
Joseph R.
quelle
BASH ist bevorzugt.
Mandar Shinde
2
@ Joseph R.: Warum benutzt du nicht $.anstelle eines Zählers?
Cuonglm
@ Gnouc könnte ich natürlich. Ich denke nur, dass dies besser lesbar ist als die Einstellung $afterauf $. - $before.
Joseph R.
Nein, ich meine: Wenn übereinstimmend, drucken $. - 1, speichern $.unter $tmp. Druck beenden $. - $tmp. Wir brauchen also keinen Zähler für vorher und nachher. Natürlich ist es weniger lesbar als deins.
Cuonglm
@ MandarShinde Bitte beachten Sie die Bearbeitung. Ich habe eine reine Bash-Antwort hinzugefügt.
Joseph R.
2

Ich habe die folgenden Befehle ausprobiert, die etwas kompliziert sind, aber genaue Ergebnisse liefern würden:

Nach dem:

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

Vor:

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

Eine awkLösung, die die Anzahl der Zeilen vor und nach dem letzten Spiel angibt

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

Grephat eine Funktion, die zählen kann, wie oft ein bestimmtes Muster gefunden wird. Wenn Sie den -cBefehl verwenden, wird dies getan. Mit dem -cund -vBefehl, diese zählen , wie oft dies nicht ein bestimmtes Muster überein

Beispiel:

grep -c -v <pattern> file

Also, wenn Sie etwas versuchen wie:

grep -c -v 192.168.x.x file.log das sollte funktionieren.

Ryekayo
quelle
Dies zählt die Anzahl der Vorkommen der Ziel-IP. Dies hat das OP nicht gefordert.
Joseph R.
Ich habe es gerade bearbeitet. Wenn er alle anderen IPs vor und nach einer bestimmten IP zählen möchte, sollte die Bearbeitung für ihn funktionieren.
Ryekayo