
Ich habe eine Datei mit einer Liste von IP-Adressen, aber einige der Zeichenfolgen sind keine IP-Adressen und ich möchte solche Zeichenfolgen durch eine Dummy-IP-Adresse ersetzen.
Ich verwende dies, grep
um nach IPs zu suchen, weiß aber nicht, wie ich das, was nicht übereinstimmt, durch eine Dummy-IP-Adresse ersetzen kann. Ich glaube, das geht mit sed
. Ich habe ein paar Dinge ausprobiert, aber nichts hat funktioniert.
cat file.txt | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
Ich habe dies, sed
um IP-Adressen in der Datei abzugleichen, aber ich habe keine Ahnung, wie ich Nicht-IP-Adressen durch eine Dummy-IP ersetzen kann.
sed -rn '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' file.txt
Eingang:
192.168.10.20
00 03
10.28.214.5
192.168.10.40
BF
192.168.10.50
Gewünschte Ausgabe:
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
Danke!
Antwort1
Ihr regulärer Ausdruck wird mit Dingen übereinstimmen, dienichtIPv4-Dotted-Quad-Adressen, sehen aber ähnlich aus (z. B. 256.256.256.256
sieht sie einer IPv4-Adresse sehr ähnlich, ist es aber nicht).
Nur zum AbgleichengültigIPv4-Adressen müssen Sie einen regulären Ausdruck wie den folgenden verwenden:
(?:(?: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]?)
oder (ohne die Perlish- ?:
Modifikatoren für nicht erfassende Gruppen):
((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]?)
und dies muss richtig verankert werden, z. B. mit und ^
an beiden Enden oder und .$
\b
\<
\>
Sehen:Kochbuch für reguläre Ausdrückevon Jan Goyvaerts und Steven Levithan, veröffentlicht von O'Reilly Media, Inc.
z.B
$ 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
Beide ändern die gesamte Eingabezeile in 192.168.0.0, sofern die Zeile nicht mit einer gültigen IPv4-Adresse übereinstimmt.
Persönlich würde ich PerlsRegexp::GemeinsamModul, das eine große Sammlung regulärer Ausdrücke für allgemeine Mustervergleichsaufgaben darstellt und praktischerweise in einem Hash namens verfügbar ist %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
Antwort2
HINWEIS: Andere haben darauf hingewiesen, dass Ihr gewählter regulärer Ausdruck für eine IPv4-Adresse fehlerhaft ist. Ich werde hier nicht versuchen, darauf einzugehen, da es an anderer Stelle ausführlich behandelt wird.
Sie können sed's verwendenChängen Sie den Befehl in Zeilen ein, die nicht ( !
) mit Ihrem RE übereinstimmen, z. B.
$ 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
Mit GNU sed können Sie vereinfachen zu
sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/!c192.168.0.0' file.txt
Antwort3
sed '/^\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\}$/!s/.*/192.168.0.0/' data
Wenn die Zeile keine gültige IPv4-Adresse ist, ersetzen Sie die aktuelle Zeile durch: 192.168.0.0
.
Ich empfehle Ihnen, stattdessen einen anderen Wert für die Dummy-Adresse zu verwenden, 192.168.0.0
aber das bleibt Ihnen und Ihren Anforderungen überlassen.
Oder dasselbe, aber mit awk
:
awk '!/^([0-9]{1,3}\.){3}[0-9]{1,3}$/ {$0="192.168.0.0"}1' data
Oder perl
:
perl -MNet::IP -ple '$_ = "192.168.0.0" unless new Net::IP($_)' data
Antwort4
Mit Perl
:
- Definieren Sie den regulären Ausdruck eines Oktetts, das aus ein bis drei Ziffern besteht, mit der Einschränkung, dass eine Null am Anfang stehen muss, sofern es sich nicht um eine einzelne Ziffer handelt.
- Übereinstimmung, dass die Zeile genau 4 durch Punkte getrennte Oktette umfasst.
- Teilen Sie die Linie in Punkte auf und stellen Sie sicher, dass alle Tupel kleiner als 256 sind.
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