
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 grep
para 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 sed
para 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 $
, \b
em 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.0
mas 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