Cuenta el número total de líneas antes / después de una coincidencia de patrón


9

Tengo una larga lista de direcciones IP, que no están en secuencia. Necesito encontrar cuántas direcciones IP hay antes / después de una dirección IP en particular. ¿Cómo puedo conseguir esto?


¿Tienes IP duplicada?
— cuonglm

No. Todas las direcciones IP son únicas.
— Mandar Shinde

¿Qué significa antes / después para una dirección IP? En particular, ¿tiene direcciones IPv4 e IPv6? ¿Cómo se comparan?
— vinc17

¿Necesita el archivo ordenado?
— cuonglm

2
@ vinc17: el archivo solo contiene direcciones IP (IPv4), no se incluyen otros datos. Si hay 1000 direcciones IP en total y la coincidencia se encuentra en la ubicación número 300, significa que hay 299 líneas antes de la coincidencia y 700 líneas después de la coincidencia.
— Mandar Shinde

Respuestas:


8

Número de líneas antes y después de una coincidencia, incluida la coincidencia (es decir, debe restar 1 del resultado si desea excluir la coincidencia):

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

Pero esto no tiene nada que ver con las direcciones IP en particular.


4

Quizás lo más fácil es,

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

Gracias @JoshepR por señalar el error


Esto solo imprime el número de línea en el que ocurrió el patrón.
— Joseph R.

@JosephR. - no, imprime cada número de línea en el que se produce cada coincidencia.
— mikeserv

@mikeserv Lo sé, pero el OP especificó que las direcciones IP son únicas. El OP tampoco quiere el número de línea donde ocurrieron las coincidencias; quieren el número de líneas antes de que ocurra el patrón y el número de líneas después de él.
— Joseph R.

@JosephR: la forma más rápida de llegar a esos recuentos es contar los números de línea dc; probablemente lo dirija directamente a mí mismo, probablemente.
— mikeserv

@mikeserv No estoy argumentando que la información de esta respuesta no sea útil, solo digo que este código por sí solo no hace lo que el OP quiere.
— Joseph R.

3

Lo hice de dos maneras, aunque creo que me gusta más:

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

Eso los guarda a todos como variables de shell actuales, y luego los evalúa en el ciclo for para la salida. Cuenta el total de líneas en el archivo wcy obtiene el primer número de línea coincidente con sed.

Su salida:

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

Yo también hice:

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

sedimprime solo los números coincidentes y de la última línea, luego trtraduce las \nlíneas electrónicas intermedias a, y readlee el primero de sedlos resultados en $mly todos los demás en $ll. Los posibles casos de coincidencias múltiples se manejan eliminando todos los resultados, excepto el último, de $llla expansión cuando se configura de nuevo más tarde.

Su salida:

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

Ambos métodos fueron probados en el archivo generado de la siguiente manera:

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 hace, por número de línea:

  1. establece la cadena de búsqueda
  2. realiza cinco bucles para asegurarse de que haya múltiples coincidencias
  3. imprime 199 ceros y "$IP"luego una línea \nelectrónica
  4. salida de tuberías a tr- que traduce ceros a \nlíneas de flujo y luego~/file

2

Aquí hay un poco de código Perl que lo hace:

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

Esto cuenta el número total de líneas antes y después de la línea que contiene la IP 192.168.1.1. Reemplace con su IP deseada.

Usando nada más que 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"

BASH es preferido.
— Mandar Shinde

2
@Joseph R .: ¿Por qué no usas en $.lugar de un contador?
— cuonglm

@Gnouc podría, por supuesto. Sólo creo que esto es más fácil de leer que el establecimiento $aftera $. - $before.
— Joseph R.

No, quiero decir: si coincide, imprima $. - 1, guarde $.en $tmp. Fin de impresión $. - $tmp. Por lo tanto, no necesitamos un contador para ambos antes y después. Por supuesto, es menos legible que el tuyo.
— cuonglm

@MandarShinde Por favor, vea la edición. Agregué una respuesta pura de Bash.
— Joseph R.

2

Estaba probando los siguientes comandos, que son un poco complicados, pero darían resultados precisos:

Después:

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

Antes de:

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

2

Una awksolución que informa el número de líneas antes y después del último partido

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

1

Greptiene una función que puede contar la cantidad de veces que se encuentra un patrón en particular. Si usa el -ccomando, lo hará. Con el comando -cy -v, esto contará cuántas veces esto no coincide con un patrón en particular

Ejemplo:

grep -c -v <pattern> file

Entonces, si intentas algo como:

grep -c -v 192.168.x.x file.log eso debería funcionar.


Esto cuenta el número de ocurrencias de la IP de destino. Esto no es lo que solicitó el OP.
— Joseph R.

Acabo de editarlo, si él está pidiendo contar todas las demás IP antes y después de una IP en particular, la edición debería funcionar para él.
— ryekayo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.