Sto avendo un lungo elenco di indirizzi IP, che non sono in sequenza. Devo trovare quanti indirizzi IP ci sono prima / dopo un determinato indirizzo IP. Come posso raggiungere questo obiettivo?
Sto avendo un lungo elenco di indirizzi IP, che non sono in sequenza. Devo trovare quanti indirizzi IP ci sono prima / dopo un determinato indirizzo IP. Come posso raggiungere questo obiettivo?
Risposte:
Numero di righe prima e dopo una partita, inclusa la partita (ad esempio, è necessario sottrarre 1 dal risultato se si desidera escludere la partita):
sed -n '0,/pattern/p' file | wc -l
sed -n '/pattern/,$p' file | wc -l
Ma questo non ha nulla a che fare con gli indirizzi IP in particolare.
Forse il più semplice è,
sed -n '/pattern/{=; q;}' file
Grazie @JoshepR per aver segnalato l'errore
dc
me stesso, probabilmente.
L'ho fatto in due modi, anche se penso che mi piaccia di più:
: $(( 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
Ciò salva tutte quelle come variabili shell correnti e le valuta successivamente nel ciclo for per l'output. Conta le linee totali nel file wc
e ottiene il primo numero di riga corrispondente sed
.
Il suo output:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Ho anche fatto:
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
stampa solo i numeri corrispondenti e dell'ultima riga, quindi tr
traduce le \n
ewline intermedie ine read
legge il primo dei sed
risultati in $ml
e tutti gli altri in $ll
. Le possibili casistiche multiple vengono gestite rimuovendo tutto tranne l'ultimo risultato $ll
dall'espansione quando lo si imposta nuovamente in un secondo momento.
Il suo output:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Entrambi i metodi sono stati testati sul file generato nel modo seguente:
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
Lo fa, per numero di riga:
"$IP"
poi una \n
ewlinetr
- che traduce gli zero in \n
ewline e poi in~/file
Ecco un po 'di codice Perl che lo fa:
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
Questo conta il numero totale di righe prima e dopo la riga che contiene l'IP 192.168.1.1
. Sostituisci con il tuo IP desiderato.
Utilizzando nient'altro che 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"
$.
un contatore?
$after
a $. - $before
.
$. - 1
, salva $.
su $tmp
. Fine stampa $. - $tmp
. Quindi non abbiamo bisogno di un contatore per entrambi prima e dopo. Ovviamente è meno leggibile del tuo.
Stavo provando i seguenti comandi, che sono un po 'complicati, ma darei risultati accurati:
Dopo:
a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l
Prima:
echo "`cat -n file | grep <Pattern> | awk '{print $1}'`-1" | bc -l
Grep
ha una funzione che può contare il numero di volte in cui viene trovato un modello particolare. Se si utilizza il -c
comando che lo farà. Con il comando -c
e -v
, questo conterà quante volte ciò non corrisponde a un modello particolare
Esempio:
grep -c -v <pattern> file
Quindi se provi qualcosa del genere:
grep -c -v 192.168.x.x file.log
dovrebbe funzionare.