Centrum skryptów - Systemy operacyjne

Jak porównać zawartość dwóch plików tekstowych?

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 porównać zawartość dwóch plików tekstowych?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Mam dwa różne pliki tekstowe. Jeden z nich zawiera listę adresów MAC pochodzących ze skanowania sieci, a drugi – listę adresów MAC naszych aktualnie zarządzanych urządzeń. Jak porównać te dwa pliki i wyeksportować to trzeciego pliku listę adresów, które nie mają odpowiadającego urządzenia?

-- SR

Cześć Skrypciarze! Odpowiedź

Cześć, SR. Na każdego przychodzi taki czas, ze chce zmienić coś w swoim życiu. Ludzie mają na to różne sposoby i w zależności od zapału i innych predyspozycji udaje im się to w mniejszym lub większym stopniu. Skrypciarz piszący te słowa postanawia cos takiego średnio co dwa tygodnie. Zazwyczaj są to postanowienia typu: od jutra biegam co rano 5 km, albo: od jutra czytam książki zamiast oglądać koszykówkę, albo coś całkiem innego, dotyczącego życia duchowego. Problem polega na tym, że rano kiedy dzwoni budzik, Skrypciarz jest w takim szoku, że od razu zapomina o wszystkich swoich postanowieniach z poprzedniego wieczora. Tym razem postanowienie jest bardzo silne i piszący te słowa Skrypciarz zmobilizował wszystkie swoje wewnętrzne siły, żeby tylko się udało. Niestety nie możemy powiedzieć dokładnie o co chodzi i na czym ma ta odmiana polegać, ponieważ nasz Skrypciarz trzyma to wszystko w głębokim sekrecie. Podobno, gdyby powiedział o co chodzi, nic by z tego nie wyszło, bo to się udaje tylko wtedy, gdy nikt o tym nie wie. Strasznie to podejrzane. Jeszcze bardziej podejrzana byłaby sytuacja, w której nastąpiłaby jakaś zmiana w jego zachowaniu, ponieważ oznaczałby to, że coś naprawdę się dzieje. Tymczasem piszący te słowa Skrypciarz w dalszym ciągu wykonuje swoje obowiązki w ten sam sposób, co dotychczas, czego dowodem jest skrypt, za pomocą którego można porównać zawartość dwóch plików tekstowych i wyłowić różnice między nimi:

Const ForReading = 1



Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile1 = objFSO.OpenTextFile("C:\Scripts\Current.txt", ForReading)



strCurrentDevices = objFile1.ReadAll

objFile1.Close



Set objFile2 = objFSO.OpenTextFile("C:\Scripts\Addresses.txt", ForReading)



Do Until objFile2.AtEndOfStream

    strAddress = objFile2.ReadLine

    If InStr(strCurrentDevices, strAddress) = 0 Then

        strNotCurrent = strNotCurrent & strAddress & vbCrLf

    End If

Loop



objFile2.Close



Wscript.Echo "Addresses without current devices: " & vbCrLf & strNotCurrent



Set objFile3 = objFSO.CreateTextFile("C:\Scripts\Differences.txt")



objFile3.WriteLine strNotCurrent

objFile3.Close

No dobra, zobaczmy, jak ten skrypt działa. Czas nie jest po naszej stronie. Coś się przecież święci. Na początek, mamy plik tekstowy o nazwie C:\Scripts\Current.txt, zawierający adresy MAC naszych aktualnie zarządzanych urządzeń. Ten plik wygląda mniej więcej tak:

00:14:A5:4D:AC:01

00:14:A5:4D:AC:03

00:14:A5:4D:AC:04

Mamy także drugi plik (C:\Scripts\Addresses.txt), zawierający wszystkie adresy MAC uzyskane podczas skanowania sieci:

00:14:A5:4D:AC:01

00:14:A5:4D:AC:02

00:14:A5:4D:AC:03

00:14:A5:4D:AC:04

00:14:A5:4D:AC:05

Musimy teraz porównać te dwa pliki i zobaczyć, czy w sieci znajdują się jakieś urządzenia (zidentyfikowane za pomocą adresu MAC), które nie pojawiają się na naszej liście aktualnie zarządzanych urządzeń. Innymi słowy, chcemy wygenerować listę niezarządzanych/nieznanych urządzeń. No to co? Trzeba wygenerować tę listę.

W samym skrypcie zaczynamy od określenia stałej o nazwie ForReading; będzie nam ona potrzebna do otwarcia i dokonania odczytu z naszych dwóch plików tekstowych. Następnie tworzymy wystąpienie obiektu Scripting.FileSystemObject, po czym stosujemy poniższy wiersz kodu i otwieramy do odczytu plik tekstowy C:\Scripts\Current.txt:

Set objFile1 = objFSO.OpenTextFile("C:\Scripts\Current.txt", ForReading)

Teraz stosujemy metodę ReadAll w celu wczytania zawartości całego pliku, zachowując tę zawartość w zmiennej o nazwie strCurrentDevices. Następnie, kiedy już nie potrzebujemy pliku Current.txt, zamykamy go za pomocą metody Close.

Mamy teraz listę adresów MAC dla wszystkich zarządzanych urządzeń. Naszym następnym krokiem będzie uzyskanie listy wszystkich adresów MAC znalezionych w sieci i sprawdzenie, czy adresy pojawiają się także na liście zarządzanych urządzeń.

W tym celu najpierw otwieramy plik C:\Scripts\Addresses.txt, także do odczytu:

Set objFile2 = objFSO.OpenTextFile("C:\Scripts\Addresses.txt", ForReading)

Z uwagi na fakt, że każdy adres MAC znajduje się w oddzielnym wierszu w pliku, uruchamiamy pętlę Do Until, która będzie działać, dopóki nie dotrze do końca pliku. (Lub, mówiąc bardziej technicznym językiem, dopóki właściwość AtEndOfStream nie osiągnie wartości True.) Wewnątrz tej pętli używamy metody ReadLine w celu odczytania pierwszego wiersza z pliku (czyli pierwszego adresu MAC) i zachowania tej wartości w zmiennej o nazwie strAddress:

strAddress = objFile2.ReadLine

W przypadku naszego pierwszego pliku oznacza to, że zmienna strAddress jest równa:

00:14:A5:4D:AC:01

To nas sprowadza do poniższego wiersza kodu:

If InStr(strCurrentDevices, strAddress) = 0 Then

Używamy teraz funkcji InStr w celu określenia, czy pierwszy adres MAC (00:14:A5:4D:AC:01) znajduje się także gdzieś na liście zarządzanych urządzeń. Jak widać, funkcja InStr ma dwa parametry: ciąg, w którym szukamy (strCurrentDevices) oraz ciąg, który chcemy znaleźć (strAddress). Funkcja InStr daje nam pozycję znaku, na której znajduje się szukany ciąg; jeżeli szukany ciąg nie może zostać odnaleziony, funkcja InStr przekaże nam wartość 0.

Innymi słowy, jeżeli InStr przekaże nam wartość 0, będzie to oznaczać, że adresu nie ma na liście zarządzanych urządzeń. Dlatego też dodajemy ten adres do bieżącego rejestru niezarządzanych urządzeń.

strNotCurrent = strNotCurrent & strAddress & vbCrLf

Ten fragment kodu jest całkiem prosty: jedyne, co tu robimy, to przypisujemy wartość do zmiennej o nazwie strNotCurrent. A jaką wartość przypisujemy tej zmiennej? Przypisujemy jej istniejącą wartość zmiennej strNotCurrent plus adres MAC, którego właśnie nie mogliśmy znaleźć (strAddress) plus znak powrotu karetki (vbCrLf). Następnie uruchamiamy pętlę i powtarzamy ten proces dla następnego adresu MAC. Po skończeniu sprawdzania wszystkich adresów MAC zamykamy plik, a następnie stosujemy poniższy wiersz kodu w celu wywołania echa wyników:

Wscript.Echo "Addresses without current devices: " & vbCrLf & strNotCurrent

Biorąc pod uwagę nasze pliki tekstowe, na ekranie wyświetlone zostaną następujące informacje:

Addresses without current devices:

00:14:A5:4D:AC:02

00:14:A5:4D:AC:05

A ponieważ chcemy zapisać te wyniki w trzecim pliku, stosujemy ten ostatni fragment kodu:

Set objFile3 = objFSO.CreateTextFile("C:\Scripts\Differences.txt")



objFile3.WriteLine strNotCurrent

objFile3.Close

W ten sposób tworzymy najpierw nowy plik tekstowy o nazwie C:\Scripts\Differences.txt. Po utworzeniu tego pliku wywołujemy metodę WriteLine w celu zapisania wartości zmiennej strNotCurrent w nowym pliku. Następnie zamykamy plik – i koniec roboty.

Oczywiście moglibyśmy także pójść w innym kierunku i poszukać zarządzanych urządzeń, które nie pojawiają się na liście adresów. Żeby to uczynić, wystarczy wczytać listę adresów, a potem wyszukać na tej liście wszystkie zarządzane urządzenia. (zadanie dokładnie odwrotne do tego, które właśnie zakończyliśmy.) Ten kod wyglądałby następująco:

Const ForReading = 1



Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile1 = objFSO.OpenTextFile("C:\Scripts\Addresses.txt", ForReading)



strAddresses = objFile1.ReadAll

objFile1.Close



Set objFile2 = objFSO.OpenTextFile("C:\Scripts\Current.txt", ForReading)



Do Until objFile2.AtEndOfStream

    strCurrent = objFile2.ReadLine

    If InStr(strAddresses, strCurrent) = 0 Then

        strNoAddress = strNoAddress & strCurrent & vbCrLf

    End If

Loop



objFile2.Close



Wscript.Echo "Devices with no address: " & vbCrLf & strNoAddress



Set objFile3 = objFSO.CreateTextFile("C:\Scripts\Differences.txt")



objFile3.WriteLine strNoAddress

objFile3.Close

Chyba nie ma potrzeby wspominać, że mamy także możliwość połączenia tych dwóch skryptów i wyszukania elementów pojawiających się w pliku A, ale nie w pliku B oraz elementów pojawiających się w pliku B, ale nie w pliku A. Ale z tym pewnie sami sobie poradzicie.

Mamy nadzieję, że nasza odpowiedź jest wyczerpująca.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne