Centrum skryptów - Systemy operacyjne

Jak pobrać adresy IP (i tylko adresy IP) z pliku tekstowego?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy.

Jak pobrać adresy IP (i tylko adresy IP) z pliku tekstowego

Cześć, Skrypciarze! Mam skrypt używający narzędzia Netsh.exe do zwracania informacji pochodzących z serwerów DHCP; informacje te są zapisywane w pliku tekstowym. Działa to świetnie, ale zależy mi na tym, aby przeanalizować pobrane dane i wyciągnąć z nich adresy IP. Jak napisać skrypt pobierający z pliku tekstowego wyłącznie adresy IP?

-- MJ

Cześć, MJ. Muszę się przyznać, że mimo niedawnej wizyty we Włoszech zapragnąłem znowu odwiedzić Europę. Ach, Stary Świat, świat rycerzy, gotyckich katedr i starożytnych ruin… a także ekscytujących, nowych możliwości biznesowych. Rzućcie okiem na to opis konferencji 2007 TechEd IT Forum, mającej się odbyć w Barcelonie:

„Najważniejsza europejska konferencja Microsoft, udostępniająca specjalistom IT szkolenia techniczne, informacje i kontakt ze społecznością, poświęcona tworzeniu, planowaniu, wdrażaniu i zarządzaniu bezpieczną siecią firmową za pomocą produktów infrastrukturalnych i technologii firmy Microsoft.”

Czy jakikolwiek specjalista IT może powstrzymać dreszczyk emocji po przeczytaniu takiej zapowiedzi? Czy ktokolwiek nie będący specjalistą IT może powstrzymać nagłe pragnienie, by nim zostać?

Cóż, jeśli firma nie zafunduje mi tego wyjazdu, gotów jestem puścić się w podróż przez Atlantyk choćby kajakiem. Po drodze będę mógł zabijać czas, pisząc skrypty, takie choćby jak ten:

Const ForReading = 1



Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)



strSearchString = objFile.ReadAll



objFile.Close



Set objRegEx = CreateObject("VBScript.RegExp")



objRegEx.Global = True   

objRegEx.Pattern = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"



Set colMatches = objRegEx.Execute(strSearchString)  



If colMatches.Count > 0 Then

    For Each strMatch in colMatches   

       Wscript.Echo strMatch.Value

    Next

End If

Zanim zajmę się wyjaśnieniem jego działania, rzućmy okiem na plik tekstowy przesłany przez MJ. Plik ten, zawierający dane pobrane i sformatowane za pomocą narzędzia Netsh.exe, wygląda mniej-więcej tak:

==========================================================================

Scope Address        - Subnet Mask                  - State                      

-Scope Name            -Comment

 192.168.120.0        - 255.255.255.0               - Active                     

 -New York, Class C    - New York, NY C

 Total No. of Scopes = 1

Jak widać, w pliku mamy dwa adresy IP: 192.168.120.0 i 255.255.255.0.

Uwaga. No tak, tak naprawdę 255.255.255.0 to maska podsieci. Nie jestem pewien, czy MJ chce, aby skrypt pobierał takie dane; za chwilę pokażemy, jak zmodyfikować powyższy skrypt w taki sposób, aby ich nie pobierał.

Zacznijmy, dla odmiany, od początku. Skrypt zaczyna się od zdefiniowania stałej o nazwie ForReading, której wartość ustawiamy na 1; użyjemy jej do otworzenia pliku. Po jej zdefiniowaniu tworzymy wystąpienie obiektu Scripting.FileSystemObject, a następnie używamy metody OpenTextFile do otworzenia pliku C:\Scripts\Test.txt do odczytu:

Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

Po otwarciu pliku używamy metody ReadAll do odczytania całej jego zawartości i przechowania tych danych w zmiennej o nazwie:

strSearchString = objFile.ReadAll

Następnie wywołujemy po prostu metodę Close i zamykamy plik. I już koniec.

A przynajmniej koniec z plikiem tekstowym. Musimy jednak zająć się jeszcze pobraniem adresów IP.

Jak stwierdza MJ w e-mailu, adresy IP mogą być dowolne. Nie mają jakiegoś wspólnego elementu, np. początku 192.168. Czy to sprawia, że ich znalezienie będzie trudniejsze? Może Was zaskoczę, ale nie. A na pewno nie, jeśli użyjemy wyrażeń regularnych.

Nie będziemy tutaj omawiać wyrażeń regularnych; jeśli Was to interesuje, zachęcamy do obejrzenia webcastu String Theory for System Administrators: An Introduction to Regular Expressions, prowadzonego przez świętej pamięci, nieodżałowanego Deana Tsaltasa.

Uwaga. No dobra, tak naprawdę Dean nie umarł. Wyjechał tylko do Kanady.

Tak czy inaczej, aby użyć w skrypcie wyrażeń regularnych, musimy utworzyć wystąpienie obiektu VBScript.RegExp:

Set objRegEx = CreateObject("VBScript.RegExp")

Po utworzeniu obiektu ustawiamy wartość właściwości Global na True; dzięki temu wyrażenie regularne wyszuka wszystkie adresy IP w ciągu wyszukiwania. (Gdybyśmy nie ustawili tej wartości na True, skrypt zatrzymałby się po znalezieniu pierwszego adresu.)

Dochodzimy do poniższego wiersza kodu:

objRegEx.Pattern = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"

Jak się okazuje, właściwość Pattern oznacza wartość, która nas interesuje (czyli w naszym wypadku adres IP.) Za chwilę wyjaśnimy, co oznacza ten dziwaczny kod. Najpier jednak zastanówmy się chwilę nad tym, jak wyglądają adresy IP. Otóż adres IP z reguły składa się z następujących fragmentów:

  • Grupa 1-3 cyfr (wartości od 0 do 9) i kropka (np. 192.)
  • Grupa 1-3 cyfr i druga kropka (np. 168.)
  • Grupa 1-3 cyfr i trzecia kropka (np. 120.)
  • Grupa 1-3 cyfr (np. 1)

Takich właśnie ciągów znaków będziemy wyszukiwać. Konstrukcja \d{1,3} oznacza: „Wyszukaj cyfry; musi ich być co najmniej jedna (1), ale nie więcej, niż 3 (3)”. Konstrukcja \. oznacza: „znajdź kropkę”. Jakie kryteria wyszukiwania ostatecznie uzyskujemy? Właśnie takie, o jakie nam chodziło:

1 do 3 cyfr (wartości od 0 do 9), po nich kropka, następnie 1 do 3 cyfr, druga kropka, następnie 1 do 3 cyfr i jeszcze jednak kropka, a w końcu 1 do 3 cyfr.

Dziwne, ale działa.

Po zdefiniowaniu wzorca wyszukiwania możemy przejść do wywołania metody Execute i przeprowadzenia wyszukiwania wyrażeń regularnych w zawartości pliku:

Set colMatches = objRegEx.Execute(strSearchString)

Jeśli metoda Execute znajdzie tekst odpowiadający wzorcowi, odpowiedni fragment zostanie przechowany w kolekcji colMatches. Dzięki temu będziemy mogli zobaczyć, czy znaleźliśmy jakieś adresy IP, sprawdzając, czy wartość Count tej kolekcji jest większa od zera:

If colMatches.Count > 0 Then

Jeśli wartość Count będzie większa od zera, możemy uruchomić pętlę For Each, która przejdzie przez wszystkie jej elementy. Wewnątrz niej wywołujemy po prostu echo naszej wartości (czyli tekst zgodny z wzorcem wyszukiwania):

Wscript.Echo strMatch.Value

Co się stanie, kiedy uruchomimy skrypt na przykładowym zestawie danych MJ? Otrzymamy coś takiego:

192.168.120.0

255.255.255.0

Co zrobić, aby usunąć z wyników maskę podsieci? W tym celu wystarczy dodać do pętli For Each instrukcję If Then, która odfiltruje wszystkie adresy zaczynające się od 255. Użyjemy funkcji Left, która sprawdzi, czy trzy znaki z lewej strony ciągu to 255:

For Each strMatch in colMatches   

    If Left(strMatch.Value, 3) <> "255" Then 

       Wscript.Echo strMatch.Value

    End If

Next

Po uruchomieniu tak zmodyfikowanego skryptu otrzymamy wynik:

192.168.120.0

Żegnaj, masko podsieci, witaj, Barcelono!

Do początku stronyDo początku strony

Centrum skryptów - Systemy operacyjne