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?
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?
Antworten:
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.
Vielleicht ist das einfachste,
sed -n '/pattern/{=; q;}' file
Vielen Dank an @JoshepR für den Hinweis auf den Fehler
dcwahrscheinlich direkt an mich selbst weiterleiten .
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:
"$IP"dann eine \nEwlinetr- übersetzt Nullen in \newlines und dann in~/fileHier 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"
$.anstelle eines Zählers?
$afterauf $. - $before.
$. - 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.
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
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.