Jak wyszukać w pliku tekstowym hasła, zapisane w innym pliku?
Skrypciarze odpowiadają na Wasze pytania
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 wyszukać w pliku tekstowym hasła, zapisane w innym pliku?
Cześć, Skrypciarze! Mam u siebie plik tekstowy, w którym znajduje się lista haseł wyszukiwania. Chciałbym napisać skrypt, który wyszuka wszystkie te hasła w drugim pliku, a następnie zgłosi, których elementów nie znalazł w drugim pliku. Jak to zrobić?
-- PH
Cześć, PH. Dobrze, że piszesz, bo muszę podzielić się z kimś smutnym doświadczeniem dnia wczorajszego. Otóż wracałem sobie do domu z pracy i poczułem się nagle jak w skeczu o sklepie z serami. Poczułem, że „coś bym wrzucił na ruszt, coś bym skubnął, poczułem ssanie w brzusiu”, zdecydowałem się więc coś z tym zrobić. Niestety sklepu z serem nie było w pobliżu, postanowiłem zatem pójść do sklepu z kanapkami i zamówiłem jedną, bodajże półmetrową, dla siebie. Jako kochający ojciec zamówiłem również taką samą dla Skrypciarskiego syna, a wiecie o co pyta mnie kasjerka? „Na miejscu czy na wynos?” Pozostawiam bez komentarza…
Albo dobra, nie wytrzymam: Czy ja wyglądam na kogoś, kto mógłby wrzucić w siebie na miejscu dwie półmetrowe kanapki??? Czy wyglądam na kogoś, kto para się obżarstwem??? To są pytania retoryczne, bo oczywiście, że NIE. Rozumiem: pycha, chciwość, gniew… ale lenistwo i obżarstwo absolutnie mnie nie dotyczą. (No, nie powiedziałabym – przyp.red.)
Co innego nasza Pani Redaktor…
(Protestuję! – przyp.red.)
Tak smakowicie zaś wygląda skrypt, który pobiera hasła z jednego pliku tekstowego, po czym wyszukuje je w drugim pliku tekstowym:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\SearchText.txt", ForReading)
strContents = objFile.ReadAll
objFile.Close
Set objFile = objFSO.OpenTextFile("C:\Scripts\Terms.txt", ForReading)
strSearchTerms = objFile.ReadAll
objFile.Close
arrSearchTerms = Split(strSearchTerms, vbCrLf)
For Each strItem in arrSearchTerms
intFound = InStr(strContents, strItem)
If intFound = 0 Then
Wscript.Echo "The search term " & strItem & " was not found."
End If
Next
Zaczynamy od zdefiniowania stałej ForReading i przypisania jej wartości 1; będziemy używać tej stałej do otwierania plików tekstowych (tak, liczba mnoga nie jest tu wynikiem zachłanności autora, jak to było z kanapkami, ale wynikiem prośby PH). Po zdefiniowaniu stałej tworzymy wystąpienie obiektu Scripting.FileSystemObject, po czym używając metody OpenTextFile otwieramy do odczytu plik C:\Scripts\SearchText.txt (to plik, który chcemy przeszukać):
Set objFile = objFSO.OpenTextFile("C:\Scripts\SearchText.txt", ForReading)
Kolejnym krokiem jest wywołanie metody ReadAll, za pomocą której odczytujemy całą zawartość pliku tekstowego oraz zapisujemy tę informację w zmiennej strContents. Dzięki temu otrzymujemy również kopię pliku, która jest teraz bezpiecznie przechowywana w pamięci. Po co nam taka kopia? Otóż zamiast przeszukiwać dokument, będziemy przeszukiwać jego kopię (tak to już się robi na tym świecie, nie pytajcie dlaczego). Następnie wywołujemy metodę Close i zamykamy plik file SearchText.txt.
Zrozumiałe jak dotąd? Na pewno zastanawiacie się, jak wygląda nasz plik tekstowy SearchText.txt (czyli wartość zmiennej strContents):
'Curiouser and curiouser!' cried Alice (she was so much surprised, that
for the moment she quite forgot how to speak good English); 'now I'm
opening out like the largest telescope that ever was! Good-bye, feet!'
(for when she looked down at her feet, they seemed to be almost out of
sight, they were getting so far off). 'Oh, my poor little feet, I wonder
who will put on your shoes and stockings for you now, dears? I'm sure
_I_ shan't be able! I shall be a great deal too far off to trouble myself
about you: you must manage the best way you can; --but I must be kind to
them,' thought Alice, 'or perhaps they won't walk the way I want to go!
Let me see: I'll give them a new pair of boots every Christmas.'
Uwaga: To oczywiście z Alicji w Krainie Czarów. Nie pamiętam dokładnie, co oni tam jedli, ale zwracam uwagę, ze jedli podwieczorek (znaczy się – spożywali), jak dobrze pamiętam, przez dwanaście godzin! Tam zawsze był czas na podwieczorek. Ech, marzenia… |
Teraz korzystamy po raz ostatni z metody OpenTextFile, otwieramy plik C:\Scripts\Terms.txt (który zawiera poszukiwane przez nas elementy), a następnie wywołujemy metodę ReadAll i tym razem przechowujemy pobrane dane w zmiennej strSearchTerms:
strSearchTerms = objFile.ReadAll
Następnie wywołujemy metodę Close i wychodzimy z pliku Terms.txt.
Wartość naszych poszukiwanych elementów strSearchTerms wygląda w następujący sposób i odzwierciedla dane sczytane z pliku tekstowego:
boots
hat
pants
shirt
shoes
telescope
Nie wygląda to za dobrze na tym etapie, bo nie oznacza nic innego, jak konieczności wyszukiwania każdego elementu osobno (tj. pierwsze wyszukiwanie będzie dotyczyć słowa boots, następne słowa hat, trzecie słowa pants, itp. itd.). Oznacza to, że musimy podzielić nasze wyszukiwanie na poszczególne elementy. Tym właśnie zajmuje się poniższy wiersz kodu:
arrSearchTerms = Split(strSearchTerms, vbCrLf)
Używamy w nim funkcji Split i konwertujemy wartość ciągu strSearchTerms na tablicę arrSearchTerms. Dzieląc w miejscu znaku powrotu karetki i nowego wiersza (vbCrLf), otrzymujemy tablicę zawierającą następujące elementy:
- boots
- hat
- pants
- shirt
- shoes
- telescope
Nie wygląda to może zachwycająco, ale w tablicy znajdziemy wszystko, czego pragniemy w życiu (a raczej czego pragnie PH w dniu dzisiejszym), czyli wszystkie interesujące nas elementy.
Oczywiście posiadanie listy elementów, które chcemy wyszukać, nie jest apogeum marzeń PH. Teraz zaczyna się cała zabawa, czyli wyszukiwanie. W tym właśnie specjalizuje się przemiły poniższy fragment kodu:
For Each strItem in arrSearchTerms
intFound = InStr(strContents, strItem)
If intFound = 0 Then
Wscript.Echo "The search term " & strItem & " was not found."
End If
Next
Ustawiliśmy tutaj pętlę For Each, która przeszła przez każdy element w tablicy arrSearchTerms. Do każdego wyszukiwanego słowa używamy funkcji InStr, która bada czy poszukiwana przez nas wartość znajduje się w pliku tekstowym czy nie (a dokładniej – w zmiennej strContents). Do tego służy poniższy wiersz kodu:
intFound = InStr(strContents, strItem)
Jeśli wyszukiwany termin zostanie znaleziony InStr returns zwróci liczbę całkowitą oznaczającą pozycję znaku w ciągu, na której zaczyna się wyszukiwany termin. Jeśli termin nie zostanie znaleziony, InStr zwróci 0. Jak utworzyć raport informujący, których terminów nie znaleziono? To proste; sprawdzamy, czy wartość zmiennej intFound (pozycja znaku początkowego) nie jest równa 0:
If intFound = 0 Then
Jeśli wartość intFound jest inna niż 0, poszukiwany termin pojawia się co najmniej raz w tekście strContents. Tak więc jeśli uzyskamy wartość inną niż 0, przechodzimy po prostu do kolejnego terminu i ponownie wykonujemy pętlę. Jeśli jednak intFound będzie równa 0, będzie to znaczyć, że terminu nie ma w tekście. W takim wypadku wywołujemy komunikat informujący, że danego terminu nie znaleziono:
Wscript.Echo "The search term " & strItem & " was not found."
Użycie naszego przykładowego tekstu i przykładowych terminów wyszukiwania da nam taki wynik:
The search term pants was not found.
The search term shirt was not found.
I to już wszystko.
P.S. Zapomniałem dodać, że po otworzeniu siatki z kanapkami w domu odkryłem, że trzy czwarte jej zawartości zajmują serwetki. Myślę, że było ich około tysiąca. Nie dość, ze podejrzewają mnie o obżarstwo, to jeszcze zakładają, że jestem flejtuchem… Chyba, że chodziło im o Skrypciarskiego syna, ale w tym wypadku nawet tysiąc serwetek nie pomoże, zajęty odpadkami musi być przecież obrus, dywan i podłoga. W innym wypadku posiłek niezaliczony.
Do początku strony |