Jak wyszukać numery telefonów we wszystkich plikach tekstowych znajdujących się w folderze?
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ć numery telefonów we wszystkich plikach tekstowych znajdujących się w folderze?
Cześć, Skrypciarze! We wczorajszym artykule pokazaliście nam, jak wyszukać numery telefonów w pliku tekstowym; obiecaliście także, że dzisiaj pokażecie, jak zmodyfikować skrypt, aby przeszukał wszystkie pliki tekstowe znajdujące się w danym folderze. Pora się wywiązać z tej obietnicy.
-- SE
Cześć, SE. Danego słowa dotrzymamy. Skrypciarze zawsze dotrzymują danego słowa. Chyba się jeszcze nie zdarzyło, żeby było inaczej, Jeżeli ktoś ma nam coś do zarzucenia, to proszę bardzo. Tylko po kolei. Wiele rzeczy można nam zarzucić, ale nie to, że jak coś obiecujemy, to nie dotrzymujemy słowa.
Oczywiście, że pokażemy skrypt umożliwiający przeszukanie wszystkich plików tekstowych znajdujących się w folderze pod kątem numerów telefonów, ale najpierw chcieliśmy przeprosić wszystkich czytelników za tę nieprzespaną noc. Naprawdę nie wiem, jak mogliśmy zostawić naszych kochanych czytelników bez dokończenia tej fascynującej opowieści i skazać ich na tę koszmarną noc. Oto więc druga część naszej opowieści o skrypcie wyszukującym numery telefonów, tym razem w plikach tekstowych znajdujących się w danym folderze:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colFileList = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='C:\Scripts'} Where " _
& "ResultClass = CIM_DataFile")
For Each objFile In colFileList
strName = objFile.FileName
strName = Replace(strName, "_", " ")
Wscript.Echo strName
Set objFile = objFSO.OpenTextFile(objFile.Name, ForReading)
strSearchString = objFile.ReadAll
objFile.Close
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Global = True
objRegEx.Pattern = "\d{3}-\d{3}-\d{4} \([a-zA-Z]*\)"
Set colMatches = objRegEx.Execute(strSearchString)
If colMatches.Count > 0 Then
For Each strMatch in colMatches
Wscript.Echo strMatch.Value
Next
End If
Wscript.Echo
Next
No właśnie, trochę przydługi ten skrypt, przynajmniej jak na rubrykę Cześć Skrypciarze! Jednak nie ma co rozpaczać, prawie wszystko zostało już omówione we wczorajszym artykule. Dlatego też ominiemy część dotyczącą stosowania tradycyjnych poleceń służących do wyszukiwania numerów telefonów i zamiast tego skoncentrujemy się na tym, żeby nasze wyszukiwanie odnosiło się do wszystkich plików znajdujących się w folderze.
Naszym pierwszym krokiem będzie (zaraz po zdefiniowaniu stałej ForReading i utworzeniu wystąpienia obiektu Scripting.FileSystemObject) podłączenie się do usługi WMI na lokalnym komputerze. I zanim ktoś zapyta – nie, nie można zastosować tego skryptu do przeszukania plików na zdalnym komputerze, a to dlatego, że obiekt FileSystemObject nie może funkcjonować zdalnie. Nie oznacza to jednak, że nie można przeszukać plików na zdalnym komputerze, a jedynie, że trzeba będzie dokonać jakichś dodatkowych modyfikacji, aby to zrobić. Więcej informacji na ten temat można znaleźć w archiwalnym artykule: Jak odczytać plik tekstowy na na zdalnym komputerze?
Po podłączeniu do usługi WMI stosujemy poniższy wiersz kodu w celu pobrania kolekcji wszystkich plików znajdujących się w folderze C:\Scripts:
Set colFileList = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='C:\Scripts'} Where " _
& "ResultClass = CIM_DataFile")
Żarty na bok: teraz wystarczy tylko zastąpić ścieżkę C:\Scripts ścieżką dostępu do folderu, gdzie zlokalizowane są nasze pliki tekstowe. Na przykład, jeżeli nasze pliki tekstowe znajdują się w folderze D:\Employees, należy zastosować poniższy wiersz kodu:
Set colFileList = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='D:\Employees'} Where " _
& "ResultClass = CIM_DataFile")
Rzeczywiście, te zapytania Associators Of nie wyglądają zbyt ciekawie. Ale nie są takie groźne, na jakie wyglądają.
Kiedy już mamy kolekcję plików z folderu, uruchamiamy pętlę For Each, która przejdzie przez wszystkie elementy w tej kolekcji (czyli przez wszystkie pliki z folderu C:\Scripts). Pierwszą rzeczą, którą zrobimy wewnątrz tej pętli będzie zastosowanie następującego wiersza kodu:
strName = objFile.FileName
strName = Replace(strName, "_", " ")
Wscript.Echo strName
Jak zauważyliśmy wczoraj, (typowy Skrypciarz: zawsze żyje przeszłością) mamy serię plików o nazwach wyglądających tak:
Jonathan_Haas.txt
Ken_Myer.txt
Pilar_Ackerman.txt
Widzimy, że każdy plik ma nazwę odpowiadającą nazwisku pracownika, którego dane są w nim zachowane. Wczoraj przeszukiwaliśmy tylko jeden plik (Ken_Myer.txt); ponieważ ścieżka dostępu do tego pliku była wpisana do naszego skryptu z klawiatury, nietrudno było się domyślić, czyj numer telefonu chcieliśmy wyszukać. (Nie, szanowna Redaktorko, niestety; chodzi o Kena Meyera.) Dzisiaj jednakże będzie inaczej: pobieramy kupę innych numerów telefonów należących do wielu innych osób. Nie ma potrzeby wspominać, że chcemy mieć wgląd w to, do kogo należą poszczególne numery telefonów. Dzięki naszemu sposobowi nazywania plików możemy po prostu sprawdzać nazwę pliku, dokonując w niej pewnej modyfikacji. W naszym pierwszym wierszu kodu uzyskujemy wartość właściwości FileName (czyli nazwy pliku bez rozszerzenia pliku) i zachowujemy ją w zmiennej o nazwie strName:
strName = objFile.FileName
Dzięki temu zmienna strName będzie miała następującą wartość:
Jonathan_Haas
Już jest dobrze, ale my zdecydowaliśmy posunąć się trochę dalej i zastąpić znak podkreślenia pustą spacją. Może Was to zaskoczy, ale zastosujemy do tego funkcję Replace skryptu VBScript, która zastępuje podkreślnik (_) pustą spacją (“ “):
strName = Replace(strName, "_", " ")
Zgadnijcie, co widzimy na ekranie kiedy wywołamy echo nowej wartości zmiennej strName? Znowu pudło, szanowna Redaktorko, prawidłowa odpowiedź to:
Jonathan Haas
Uwaga. To chyba nie jest najłatwiejszy dzień dla naszej Redaktorki. Wydaje nam się, że może być w lekkim szoku, ponieważ piszący te słowa Skrypciarz robi to, co mówił, że zrobi i to bez żadnego zaganiania, przypominania, poganiania i gróźb. Ale przecież co obietnica, to obietnica. |
Wywoławszy echo nazwy pracownika, możemy wyszukać numery telefonów w pierwszym pliku (Jonathan_Haas.txt). Od tego momentu, w zasadzie większość skryptu wygląda tak samo jak skrypt omówiony wczoraj. Z jednym wszakże wyjątkiem i to niemałym: kiedy wywołujemy metodę OpenTextFile (którą musimy wywołać w celu otwarcia o odczytania pliku), nie stosujemy ścieżki C:\Scripts\Ken_Myer.txt wpisanej z klawiatury. Zamiast tego, przekazujemy do metody wartość właściwości Name (która, tak się składa, jest taka sama jak ścieżka dostępu do pliku):
Set objFile = objFSO.OpenTextFile(objFile.Name, ForReading)
Teraz dokonujemy odczytu pliku, zachowujemy jego zawartość w zmiennej o nazwie strSearchString, a następnie stosujemy tradycyjne wyrażenie do przeszukania tej zawartości pod kątem numerów telefonów. Po wywołaniu echa wszystkich odnalezionych w pliku numerów stosujemy polecenie Wscript.Echo w celu wywołania echa pustego wiersza na ekran. Kiedy skończymy z Jonathanem Haas, kontynuujemy działanie pętli i powtarzamy proces dla następnego pliku z kolekcji. Kiedy skończymy z wszystkimi plikami, nasz ekran powinien wyglądać tak:
Jonathan Haas
425-555-4241 (office)
425-555-9977 (home)
Ken Myer
425-555-1212 (office)
425-555-5656 (cell)
425-555-3434 (home)
Pilar Ackerman
425-555-2134 (office)
425-555-6341 (cell)
425-555-8900 (home)
O to przecież nam chodziło. Chcecie wykonać podobne wyszukiwanie w odniesieniu do wszystkich plików znajdujących się w folderze? Żaden problem. Wystarczy postępować według wzoru. Należy wykorzystać usługę WMI do uzyskania kolekcji wszystkich plików, a następnie zastosować właściwość Name do pobrania ścieżki dla danego pliku (na przykład, jeżeli chcemy przekazać ścieżkę do innego obiektu, jak np. FileSystemObject). Często otrzymujemy pytania dotyczące odczytu/zapisu w odniesieniu do wszystkich plików znajdujących się w danym folderze. Teraz już wiadomo, jak!
Na tym się kończy nasz dwuczęściowy epizod o wyszukiwaniu numerów telefonów w plikach tekstowych. Będziemy się starać, żeby kilkuczęściowe serie już więcej się u nas nie pojawiły. Nie będzie to łatwe, co mamy teraz zrobić z pierwszymi 67 artykułami z planowanej na 300 części serii o deklarowaniu zmiennych? Ale nie martwcie się, jakoś sobie poradzimy.
Uwaga. Czy naprawdę mieliśmy zamiar napisać serię 300 artykułów o deklarowaniu zmiennych? Tak naprawdę to nie. Ale chcieliśmy napisać pierwszych 5 albo 6 części, a potem powtarzać je do oporu. Tak sobie oszacowaliśmy, że po przeczytaniu 5 następujących po sobie artykułów o zmiennych odpadliby już wszyscy czytelnicy (i redaktorzy), więc nikt by nie zauważył, że cokolwiek powtarzamy. |
Do początku strony |