IP Adresse bzw. IP Adresse/Netzmaske im Text suchen

  • Hallo,
    ich hatte hier bereits eine ähnliche Frage gestellt. Nun haben sich aber weitere Herausforderungen ergeben. :P

    Ich möchte in einem Text nach allen IP Adressen bzw. mach IP Adressen mit Maske suchen. Dazu habe ich folgende Funktion:

    [autoit]

    #include <Array.au3>

    [/autoit][autoit][/autoit][autoit]

    IP_oder_IP_Netze_aus_Zwischenablage()

    [/autoit][autoit][/autoit][autoit]

    Func IP_oder_IP_Netze_aus_Zwischenablage()
    Local $aIP_Netze

    [/autoit][autoit][/autoit][autoit]

    ;aus dem Text die IP Adresse bzw. IP Adresse/Netzmaske suchen und in Array ablegen
    $aIP_Netze = StringRegExp(ClipGet(), '(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?: ?/\d{1,2})?', 3)

    [/autoit][autoit][/autoit][autoit]

    if @error Then ;wurde denn auch eine IP Adresse in der Zwischenablage gefunden?
    Msgbox(64, "Fehler", "Keine IP Netze in der Zwischenablage gefunden!")
    Return
    EndIf

    [/autoit][autoit][/autoit][autoit]

    $aIP_Netze = _ArrayUnique($aIP_Netze) ;Doppelte Eintrage aus der Liste entfernen

    [/autoit][autoit][/autoit][autoit]

    _ArrayToClip($aIP_Netze, 1) ;Ergebnis in die Zwischenablage

    [/autoit][autoit][/autoit][autoit]

    MsgBox(0, "Ergebnis", "In der Zwischenablage wurden " & $aIP_Netze[0] & " IP Adressen mit Netzwerkmaske gefunden und als Liste zurück in die Zwischenablage kopiert." )
    EndFunc

    [/autoit]

    Wenn ich dieser Funktion aber folgendes gebe:

    Kommt das folgende Ergebnis:

    Hat jemand eine Idee wie ich das noch optimieren könnte? ;)

    Gruß Ingo

    Einmal editiert, zuletzt von Donsen64 (5. August 2014 um 12:11)

  • Dein Problem sind die folgenden Einträge?:

    10.11.75.0/25
    5.255.255.0


    Falls ja - "\b" (Wortgrenze) im regulären Ausdruck sollte da helfen:

    Code
    "\b(?:\d{1,3}\.){3}\d{1,3}\b(?: ?/ ?\d{1,2}\b(?!\.))?"

    Ansonsten:

    • Warum soll die Funktion nur aus der Zwischenablage filtern können? Kannst ja auch mit einem optionalen Parameter im Stile von [autoit]Func IP_oder_IP_Netze_aus_Zwischenablage($s_Text = ClipGet())[/autoit] arbeiten. Dann bist du flexibler was die Eingabe angeht.
    • Es werden auch ungültige IP-Adressden wie z.B. 270.0.0.0 gefunden. Es gibt auch RegEx-Konstrukte mit dem man schon beim Matching auf korrekte IPs hin checken kann. Hier mal eines von vielen (matcht nur reine IP-Adressen - diese aber mit Bereichsprüfung):
      Code
      (?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}
    • Vor dem ArrayUnique müsstest du noch die Leerzeichen killen. Sonst würdest du bei "10.11.72.0/24" und "10.11.72.0 / 24" immer noch zwei Matches statt einem finden obwohl deren Aussage die Selbe ist.
    • Wenn du IP und Mask als Return-Group nimmst kannst du sie danach getrennt behandeln und z.B. nur nach IP-Adresse filtern unabhängig von der Mask.

    Einmal editiert, zuletzt von AspirinJunkie (4. August 2014 um 12:12)

  • Hallo,
    vielen Dank für die Antwort, das verbessert schon mal die Ausgabe auf:

    Auch vielen Dank für die zusätzlichen Hinweise! Die Funktion hat in der Zielumgebung einen Übergabewert. Habe ich nur hier im Forum so gemacht, um das einfacher zu halten. Im Original erfolgt da noch eine Beseitigung der Freizeichen und das Ergebnis wird in einer weiteren Funktion noch zusätzlich auf seine Richtigkeit geprüft.

    Was mir jetzt allerdings noch Kopfzerbrechen macht ist die Tatsache, das er die folgenden Schreibweisen nicht als IP/Netzmaske erkennt:

    Zitat

    10.11.74.0 255.255.255.0
    10.11.75.0/255.255.255.0
    10.11.76.0/ 255.255.255.0
    10.11.77.0/ 255.255.0.0
    10.11.78.0 / 255.255.255.0

    Könnte man die Erkennung auch mit einbauen?

    Gruß Ingo

  • Klar - das Pattern wird dann aber ein bisschen komplexer:

    [autoit]

    Global $s_Pattern = "(?x) " & @CRLF & _
    "(\b(?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}\b) # erste IP-Adresse (mit Wertebereichscheck) " & @CRLF & _
    "(?: # Beginn der optionalen Netzmaske " & @CRLF & _
    " \s?/?\s? # das optionale Trennzeichen mit eventuellen Leerzeichen " & @CRLF & _
    " \b( # falls etwas existiert soll es auch als Group gematcht werden " & @CRLF & _
    " \d{1,2}(?!\.) # Die Netzmaske als einfache Zahl (=Anzahl der 1-Bits in der Maske)" & @CRLF & _
    " | " & @CRLF & _
    " (?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4} # Die Netzmaske als IP-Maske " & @CRLF & _
    " )\b " & @CRLF & _
    ")?"

    [/autoit][autoit][/autoit][autoit]

    $a_Result = StringRegExp(ClipGet(), $s_Pattern, 4)
    If Not @error Then
    For $i In $a_Result
    ConsoleWrite(StringFormat("%15s\t\t%-15s\n", $i[1], (UBound($i) > 2) ? $i[2] : ""))
    Next
    Else
    MsgBox(48, "", "Nix gefunden")
    EndIf

    [/autoit]

    Edit: Wenn du es übertreiben willst: Ich hab hier noch die Variante, welche auch die Subnetzmaske auf Korrektheit hin überprüft (Patternquelle: >>Hier<<).
    Wenn man eine falsche Subnetmaske einträgt, wird diese dann als normale IP-Adresse gematcht.:

    Variante mit Check auf korrekte Subnetzmaske
    [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $s_Pattern = "(?x) " & @CRLF & _
    "(\b(?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}\b) # erste IP-Adresse (mit Wertebereichscheck) " & @CRLF & _
    "(?: # Beginn der optionalen Netzmaske " & @CRLF & _
    " \s?/?\s? # das optionale Trennzeichen mit eventuellen Leerzeichen " & @CRLF & _
    " \b( # falls etwas existiert soll es auch als Group gematcht werden " & @CRLF & _
    " ([1-9]|[0-2][0-9]|3[0-2])(?!\.) # Die Netzmaske als einfache Zahl von 1-32 (=Anzahl der 1-Bits in der Maske)" & @CRLF & _
    " | " & @CRLF & _
    " (?:(?:128|192|224|240|248|252|254)\.0\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0)|255\.(?:0|128|192|224|240|248|252|254))))) # Die Netzmaske als IP-Maske " & @CRLF & _
    " )\b " & @CRLF & _
    ")?"

    [/autoit] [autoit][/autoit] [autoit]

    $a_Result = StringRegExp(ClipGet(), $s_Pattern, 4)

    [/autoit] [autoit][/autoit] [autoit]

    If Not @error Then
    For $i In $a_Result
    ConsoleWrite(StringFormat("%15s\t\t%-15s\n", $i[1], (UBound($i) > 2) ? $i[2] : ""))
    Next
    Else
    MsgBox(48, "", "Nix gefunden")
    EndIf

    [/autoit]


    Edit2: Ok wenn dann richtig - nun habe ich in der erweiterten Variante auch noch die Netzmaskenvariante in der Form einer einfachen Zahl auf den Bereich 1-32 begrenzt. ;)

    3 Mal editiert, zuletzt von AspirinJunkie (4. August 2014 um 18:51)

  • Hallo,
    na das nenne ich mal eine Antwort super vielen Dank dafür. Dazu hätte ich bestimmt Tage gebraucht. :rock:

    Nur eine Frage habe ich jetzt noch:
    Du verwendest bei StringRegExp das Flag 4. Dadurch wird scheinbar etwas sehr "spezielles" in dem Array zurück gegeben. Denn _ArrayDisplay($a_Result) zeigt mir nur ein leeres Array. ?(
    Wie bekomme ich das so umgeformt, dass ich normalen Text dort drin habe, den ich weiter verarbeiten kann?

    Nochmals vielen Dank für deine Hilfe!!!!

    Gruß Ingo

  • Das ist tatsächlich etwas "spezielles".
    Zurückgegeben wird ein Array-In-Array.
    Jedes Element dieses Arrays ist wiederrum selbst ein Array.
    Wenn wir es mit einem 2D-Array vergleichen wird schnell der große Vorteil klar: Bei einem 2D-Array ist die Spaltenanzahl (und damit die Größe der 2. Dimension) für alle Elemente gleich und fest.
    Bei einem Array-In-Array ist dies hingegen flexibel.
    Hier konkret hat das einen Vorteil: Es gibt pro Fund nicht immer die selbe Anzahl an Groups. Entweder du bekommst nur eine IP (1 Element) oder du bekommst IP+Subnetzmaske (2 Elemente).

    Um nun auf ein Element zuzugreifen wird nicht wie beim 2D-Array in eckigen Klammern erst die Zeile und die Spalte angegeben, sondern das innere Array muss erst einmal in eine temporäre Variable gepackt werden.
    Wie man das mit Hilfe einer For-In-Schleife macht habe ich schon gezeigt.
    Manuell macht man es z.B. so:

    [autoit]

    $a_Result = StringRegExp(ClipGet(), $s_Pattern, 4)
    $a_Temp = $a_Result[2] ; Das dritte Array (und damit den dritten RegEx-Fund) in Array $a_Temp speichern
    _ArrayDisplay($a_Temp)

    [/autoit]


    Damit kannst du dir also auch eine For-To Schleife mit $i als Zählervariable nehmen.
    For-In ist für diesen Zweck aber einfacher.

  • Hallo AspirinJunkie,
    klasse erklärt!!! Mit den Informationen kann ich das umsetzen.

    Ich kann mich nur nochmals sehr herzlich bei dir für deine Hilfe bedanken!!! :rock:

    Gruß Ingo

  • Hallo,
    ich habe noch mal weiter getestet und leider noch einen erlaubten Sonderfall gefunden bei denen die Pattern noch nicht funktionieren:

    10.11.70.1/255.255.255.255 = nur diese einen IP Adresse

    Wie muss ich dazu die Pattern anpassen?

    Gruß Ingo

  • Bin kein Netzerwerkexperte aber meiner Meinung nach macht diese Subnetzmaske wenig Sinn, da dies bedeuten würde, dass in diesem Subnetz keine Adresse liegt.
    Aber wenn es mit rein muss, dann mach in meinem letzten ausführlichen Beispiel hinter die letzte "254" ein "|255".

  • Hallo,
    ich muss den alten Fall nochmal vorholen.

    Mit alle 255 mach schon Sinn, denn dies bedeutet es handelt sich um eine einzelne IP Adresse. Habe ich auch umgesetzt und die folgende Funktion daraus gebaut.

    Spoiler anzeigen
    [autoit]


    _StringSearchIPorIPNetwork("Voice_192.168.1.0/24;Floor 8 and 9", "NoModify")

    [/autoit] [autoit][/autoit] [autoit]

    Func _StringSearchIPorIPNetwork($sText, $sReturnType = "NoModify")
    #cs ================================================================================
    UDF Name..........: _StringSearchIPorIPNetwork
    UDF Version.......: 1.0
    Change Date.......: 2014-08-10
    UDF Description...: sucht in einem Text alle IP Adressen oder IP/Netzwerk Kombinationen heraus und zwar
    nur solche Kombinationen die auch zulässig sind
    Author(s).........: Ingo (Basis: http://www.autoit.de/index.php?page=Thread&threadID=45397&)

    [/autoit] [autoit][/autoit] [autoit]

    Parameter(s)......: $sText => Text in dem gesucht werden soll
    $sReturnType => in welchem Format werden die Netzwerkmasken zurück gegeben
    "NoModify" (default) = so wie gefunden
    "Suffix" = in Suffix Schreibweise
    "NetMask" = Es wird immer eine lange Netzmaske zurück gegeben
    "NoNetMask" = Es wird nur die IP zurück gegeben ohne eine eventuell vorhandene Netzmaske

    [/autoit] [autoit][/autoit] [autoit]

    Return Value......: Array mit allen gefundenen IP oder IP/Netzwerk Kombinationen
    Fehler: 0 es wurde nichts im Text gefunden
    #ce ================================================================================
    Local $aResult
    Local $aTEMP
    Local $sPattern = "(?x) " & @CRLF & _
    "(\b(?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}\b) # erste IP-Adresse (mit Wertebereichscheck) " & @CRLF & _
    "(?: # Beginn der optionalen Netzmaske " & @CRLF & _
    " \s?/?\s? # das optionale Trennzeichen mit eventuellen Leerzeichen " & @CRLF & _
    " \b( # falls etwas existiert soll es auch als Group gematcht werden " & @CRLF & _
    " ([1-9]|[0-2][0-9]|3[0-2])(?!\.) # Die Netzmaske als einfache Zahl von 1-32 (=Anzahl der 1-Bits in der Maske)" & @CRLF & _
    " | " & @CRLF & _
    " (?:(?:0|128|192|224|240|248|252|254)\.0\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0)|255\.(?:0|128|192|224|240|248|252|254|255))))) # Die Netzmaske als IP-Maske " & @CRLF & _
    " )\b " & @CRLF & _
    ")?"

    [/autoit] [autoit][/autoit] [autoit]

    ;doppelte Freizeichen aus dem Text entfernen
    $sText = StringReplace($sText, " ", " ")

    [/autoit] [autoit][/autoit] [autoit]

    ;im Text nach IP oder Netzwerke suchen
    $aResult = StringRegExp($sText, $sPattern, 4)

    [/autoit] [autoit][/autoit] [autoit]

    If Not @error Then
    For $i=0 To UBound($aResult)-1
    $aTEMP = $aResult[$i]

    [/autoit] [autoit][/autoit] [autoit]

    If UBound($aTEMP) > 2 Then
    ;es wurde IP/Netzmaske gefunden
    Select
    Case $sReturnType = "Suffix" ;in Suffix Schreibweise zurück geben
    $aResult[$i] = $aTEMP[1] & "/" & INUDF_NetMaskOrSuffixTranslate($aTEMP[2], "Suffix")

    [/autoit] [autoit][/autoit] [autoit]

    Case $sReturnType = "NetMask" ;Es wird immer eine lange Netzmaske zurück gegeben
    $aResult[$i] = $aTEMP[1] & "/" & INUDF_NetMaskOrSuffixTranslate($aTEMP[2], "NetMask")

    [/autoit] [autoit][/autoit] [autoit]

    Case $sReturnType = "NoModify"
    $aResult[$i] = $aTEMP[1] & "/" & $aTEMP[2]

    [/autoit] [autoit][/autoit] [autoit]

    Case $sReturnType = "NoNetMask"
    $aResult[$i] = $aTEMP[1]

    [/autoit] [autoit][/autoit] [autoit]

    Case Else
    Return 'Error wrong $ReturnType was handed over to _StringSearchIPorIPNetwork($sText, $sReturnType = "Auto")'
    EndSelect

    [/autoit] [autoit][/autoit] [autoit]

    Else ;es wurde nur eine einfache IP Adresse gefunden
    $aResult[$i] = $aTEMP[1]
    EndIf
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return($aResult)
    Else
    Return 0 ;Nix gefunden
    EndIf
    EndFunc

    [/autoit]

    Die Funktion funktioniert auch soweit super!

    Allerdings findet er nichts wenn ich so etwas "Voice_192.168.1.0/24;Floor 8 and 9" übergebe. Ich vermute dazu muss ich den Suchstring nochmals anpassen. Aber wie kann ich mir nicht vorstellen. X(

    Hat jemand eine Idee dazu?

    Gruß Ingo

  • Hallo AspirinJunkie,
    das klappt schon mal sehr gut! Vielen Dank dafür!!! :rock:

    Nur bei der folgenden Konstellation wird die Netzwerkmaske nicht erkannt:

    Code
    Voice_192.168.1.0/24_Floor 8 and 9


    Da findet er nur 192.168.1.0 aber nicht 192.168.1.0/24.

    Noch eine Idee wie ich auch das abbilden kann?

    Gruß Ingo

  • [autoit]

    Global $s_Pattern = "(?x) " & @CRLF & _
    "((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}\b) # erste IP-Adresse (mit Wertebereichscheck) " & @CRLF & _
    "(?: # Beginn der optionalen Netzmaske " & @CRLF & _
    " \s?/?\s? # das optionale Trennzeichen mit eventuellen Leerzeichen " & @CRLF & _
    " \b( # falls etwas existiert soll es auch als Group gematcht werden " & @CRLF & _
    " \d{1,2}(?!\.) # Die Netzmaske als einfache Zahl (=Anzahl der 1-Bits in der Maske)" & @CRLF & _
    " | " & @CRLF & _
    " (?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4} # Die Netzmaske als IP-Maske " & @CRLF & _
    " )(?:[^\d]|$) " & @CRLF & _
    ")?"

    [/autoit]

    Einmal editiert, zuletzt von AspirinJunkie (11. März 2015 um 15:52)

  • Hallo AspirinJunkie,
    das funktioniert, klasse Arbeit vielen Dank dafür!!! :rock:

    Es werden jetzt zwar auch nicht erlaubte Netzmasken (z.B. 10.11.73.0 / 44 >>> darf max. von 0 - 32 sein) akzeptiert, aber das werde ich anders abfangen.

    Vielen Dank nochmals für die super Hilfe von dir und hier im Forum!!

    Gruß Ingo

  • [autoit]

    Global $s_Pattern = "(?x) " & @CRLF & _
    "((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}\b) # erste IP-Adresse (mit Wertebereichscheck) " & @CRLF & _
    "(?: # Beginn der optionalen Netzmaske " & @CRLF & _
    " \s?/?\s? # das optionale Trennzeichen mit eventuellen Leerzeichen " & @CRLF & _
    " \b( # falls etwas existiert soll es auch als Group gematcht werden " & @CRLF & _
    " ([1-9]|[0-2][0-9]|3[0-2])(?!\.) # Die Netzmaske als einfache Zahl (=Anzahl der 1-Bits in der Maske)" & @CRLF & _
    " | " & @CRLF & _
    " (?:(?:128|192|224|240|248|252|254)\.0\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0)|255\.(?:0|128|192|224|240|248|252|254|255))))) # Die Netzmaske als IP-Maske " & @CRLF & _
    " )(?:[^\d]|$) " & @CRLF & _
    ")?"

    [/autoit]
  • [autoit]

    Global $s_Pattern = "(?x) " & @CRLF & _
    "((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}\b) # erste IP-Adresse (mit Wertebereichscheck) " & @CRLF & _
    "(?: # Beginn der optionalen Netzmaske " & @CRLF & _
    " \s?/?\s? # das optionale Trennzeichen mit eventuellen Leerzeichen " & @CRLF & _
    " \b( # falls etwas existiert soll es auch als Group gematcht werden " & @CRLF & _
    " ([1-9]|[0-2][0-9]|3[0-2])(?!\.) # Die Netzmaske als einfache Zahl (=Anzahl der 1-Bits in der Maske)" & @CRLF & _
    " | " & @CRLF & _
    " (?:(?:0|128|192|224|240|248|252|254)\.0\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0\.0)|(?:255\.(?:(?:(?:0|128|192|224|240|248|252|254)\.0)|255\.(?:0|128|192|224|240|248|252|254|255))))) # Die Netzmaske als IP-Maske " & @CRLF & _
    " )(?:[^\d]|$) " & @CRLF & _
    ")?"

    [/autoit]

    Hallo,
    eine Kleinigkeit habe ich noch geändert, weil dieser 10.11.70.1/0.0.0.0 Sonderfall noch nicht abgedeckt war. Jetzt sollte es perfekt sein :D . Zu mindestens fallen mir keine Konstellationen ein bei denen es nicht funktioniert.

    Vielen Dank nochmals an alle!

    Gruß Ingo