Como substituir uma string que NÃO corresponde ao endereço IP por um endereço IP fictício?

Como substituir uma string que NÃO corresponde ao endereço IP por um endereço IP fictício?

Eu tenho um arquivo com uma lista de endereços IP, mas algumas strings não são endereços IP e quero substituí-las por um endereço IP fictício.

Estou usando isso greppara procurar IP; mas não sei como substituir o que não corresponde a um endereço IP fictício. Eu acredito que isso pode ser feito com sed. Tentei algumas coisas, mas nenhuma delas funcionou.

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

Eu tenho isso sedpara corresponder aos endereços IP no arquivo, mas não tenho ideia de como substituir endereços não IP por um IP fictício.

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

Entrada:

192.168.10.20
00 03
10.28.214.5
192.168.10.40
BF
192.168.10.50

Saída desejada:

192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

Obrigado!

Responder1

Seu regexp corresponderá às coisas que sãonãoEndereços IPv4 pontilhados-quadrados, mas semelhantes a eles (por exemplo, 256.256.256.256- parece muito com um endereço IPv4, mas não é).

Para combinar apenasválidoEndereços IPv4, você precisa usar um regex 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]?)

ou (sem os ?:modificadores de grupo perlish de não captura):

((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]?)

e isso precisa ser devidamente ancorado, por exemplo, com ^e $, \bem ambas as extremidades, ou \<e \>.

Ver:Livro de receitas de expressões regularespor Jan Goyvaerts e Steven Levithan, publicado pela O'Reilly Media, Inc.

por exemplo

$ 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 alteram toda a linha de entrada para 192.168.0.0, a menos que a linha corresponda a um endereço IPv4 válido.

Pessoalmente, eu usaria o PerlRegexp::Comummodule, que é uma grande coleção de regexes para tarefas comuns de correspondência de padrões, convenientemente disponível em um hash chamado %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

Responder2

NOTA: outros apontaram que a expressão regular escolhida para um endereço IPv4 é falha. Não tentarei abordar isso aqui, pois é bem abordado em outro lugar.

Você pode usar sedccomando hange em linhas que não ( !) correspondem ao seu RE, ex.

$ 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

Com o GNU sed, você pode simplificar para

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

Responder3

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

Se a linha não for um endereço IPv4 válido, substitua a linha atual por : 192.168.0.0.

Aconselho você a usar outro valor para o endereço fictício em vez de, 192.168.0.0mas isso depende de você e de suas necessidades.

Ou o mesmo, mas com awk:

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

Ou perl:

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

Responder4

Com Perl:

  • defina o regex de um octeto que compreende de um a três dígitos com a restrição de que seja inicial diferente de zero, a menos que seja de um único dígito.
  • corresponda que a linha compreende exatamente 4 octetos separados por pontos.
  • divida a linha em pontos e que todas as tuplas sejam menores que 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

informação relacionada