¿Cómo reemplazar una cadena que NO coincide con la dirección IP con una dirección IP ficticia?

¿Cómo reemplazar una cadena que NO coincide con la dirección IP con una dirección IP ficticia?

Tengo un archivo con una lista de direcciones IP, pero algunas de las cadenas no son direcciones IP y quiero reemplazarlas con una dirección IP ficticia.

Estoy usando esto greppara buscar IP; pero no sé cómo reemplazar lo que no coincide con una dirección IP ficticia. Creo que esto se puede hacer con sed. Intenté algunas cosas pero ninguna funcionó.

cat file.txt | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'

Tengo esto sedpara que coincida con las direcciones IP en el archivo, pero no tengo idea de cómo reemplazar las direcciones que no son IP con una IP ficticia.

sed -rn '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' file.txt

Aporte:

192.168.10.20
00 03
10.28.214.5
192.168.10.40
BF
192.168.10.50

Salida deseada:

192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

¡Gracias!

Respuesta1

Su expresión regular coincidirá con cosas que sonnoDirecciones IPv4 de cuatro puntos con puntos, pero se parecen a ellas (por ejemplo 256.256.256.256, se parecen mucho a una dirección IPv4, pero no lo son).

Para igualar soloválidoDirecciones IPv4, necesita usar una expresión regular como:

(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

o (sin los ?:modificadores de grupo perlish no capturados):

((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

y este debe estar correctamente anclado, por ejemplo con ^y $, \ben ambos extremos, o \<y \>.

Ver:Libro de cocina de expresiones regularespor Jan Goyvaerts y Steven Levithan, publicado por O'Reilly Media, Inc.

p.ej

$ sed -E '/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/!s/.*/192.168.0.0/' file.txt 
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
$ perl -p -e 's/.*/192.168.0.0/ unless m/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/' file.txt 
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

Ambos cambian la línea de entrada completa a 192.168.0.0 a menos que la línea coincida con una dirección IPv4 válida.

Personalmente, usaría Perl.expresión regular::comúnmódulo, que es una gran colección de expresiones regulares para tareas comunes de coincidencia de patrones, convenientemente disponible en un hash llamado %RE.

$ perl -MRegexp::Common -p -e 's/.*/192.168.0.0/ unless m/^$RE{net}{IPv4}$/' file.txt 
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

Respuesta2

NOTA: otros han señalado que la expresión regular que eligió para una dirección IPv4 es defectuosa. No intentaré abordar ese tema aquí ya que está bien tratado en otros lugares.

Puedes usar sedCcambie el comando en líneas que no !coincidan ( ) con su RE, ej.

$ sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/!c\
192.168.0.0
' file.txt
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

Con GNU sed, puedes simplificar a

sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/!c192.168.0.0' file.txt

Respuesta3

sed '/^\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\}$/!s/.*/192.168.0.0/' data

Si la línea no es una dirección IPv4 válida, reemplace la línea actual con: 192.168.0.0.

Le aconsejo que utilice otro valor para la dirección ficticia en lugar de 192.168.0.0pero esto depende de usted y de sus necesidades.

O lo mismo pero con awk:

awk '!/^([0-9]{1,3}\.){3}[0-9]{1,3}$/ {$0="192.168.0.0"}1' data

O perl:

perl -MNet::IP -ple '$_ = "192.168.0.0" unless new Net::IP($_)' data

Respuesta4

Con Perl:

  • defina la expresión regular de un octeto que comprende de uno a tres dígitos con la restricción de que sea distinto de cero a menos que sea de un solo dígito.
  • coincide que la línea comprende exactamente 4 octetos separados por puntos.
  • divida la línea en puntos y que todas las tuplas sean menores de 256.
dummy=192.168.0.0 \
perl -MList::Util=all -lpe '
  $octet //= qr/(?!0\d)\d{1,3}/;

  /^$octet(?:[.]$octet){3}$/ &&
   all { $_<256 } split /[.]/ or
     $_ = $ENV{dummy};
' file

información relacionada