Centrum skryptów - Systemy operacyjne

Jak warunkowo dodać wiersze do pliku tekstowego?

Udostępnij na: Facebook

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 warunkowo dodać wiersze do pliku tekstowego?

Cześć, Skrypciarze! Potrzebny mi skrypt, który może odczytać plik i w zależności od jego zawartości wstawić do niego kilka dodatkowych wierszy. Możecie mi z tym pomóc?

-- JS

Cześć, JS. Na pewno wielu z Was słyszało już, że firma Microsoft zaproponowała wykupienie Yahoo!. Wartość oferty to obecnie jakieś 42 miliardy dolarów. (Ponieważ oferta częściowo opiera się na cenach akcji, wartość przedmiotu umowy zmienia się codziennie). Jak dotąd, Yahoo! zażądało jeszcze lepszej oferty, pisząc w liście do CEO firmy Microsoft, Steve’a Ballmera: „Jesteśmy bardzo zaangażowani w wybranie takiej ścieżki, która zmaksymalizuje wartość naszych akcji i nie dopuścimy, aby ktokolwiek (w tym firma Microsoft) przejęła firmę Yahoo! za cenę nieodzwierciedlającą jej prawdziwej wartości”.

Ponieważ oczywiście firma, która nie może się pochwalić żadnymi osiągnięciami (w tym zarobkami) jest warta o wiele więcej niż 42 miliardy dolarów.

Ważne:
Uwaga Redaktorki: Tak, wygląda na to, że Skrypciarz odpowiedzialny za dzisiejszy artykuł znowu próbuje ściągnąć na siebie (i na Redaktorkę) kłopoty. Ostatnim razem, kiedy Skrypciarz wspomniał nazwę znanej witryny sieci Web, artykuł został natychmiast usunięty. Kiedy ludzie zobaczą, co tutaj mamy, cóż… czytajcie szybko, zapewne jesteście nielicznymi czytelnikami, którzy mogą przeczytać ten artykuł.

 

Firma Microsoft nie odpowiedziała na tę ostatnią salwę od Yahoo!, co może oznaczać tylko jedno: Skrypciarze muszą wkroczyć do akcji. Oczywiście pieniądze nie są ważne dla władz Yahoo!. Gdyby tak było, przyjęliby te 42 miliardy i zniknęli. Musi im chodzić o coś lepszego i o wiele bardziej znaczącego niż pieniądze. Dlatego Skrypciarze zdecydowali się zająć negocjacjami: jeśli firma Yahoo! zdecyduje się na sprzedaż, my z kolei damy każdemu akcjonariuszowi Yahoo! laleczkę dr Scripto. Tego się nie da kupić nawet za 42 miliardy dolarów.

Uwaga. Jeśli już koniecznie chcecie tak na to spojrzeć, z technicznego punktu widzenia za 42 miliardy dolarów można kupić ponad 4 miliardy laleczek dr Scripto. Ale nie mówmy o tym kolegom z Yahoo!, ok.?

W każdym razie, jeśli zarząd firmy Yahoo! czyta te słowa, dajcie nam znać, co o tym myślicie. Chcę tylko dodać, że ta oferta jest ostateczna. Nie dlatego, że nie chcemy negocjować, tylko dlatego, że oprócz kilku laleczek nie mamy czym negocjować. Redaktorka mówi, że dorzuci swojego Lexusa, ale sami będziecie musieli się dogadać, kto i kiedy będzie nim jeździł.

Uwaga. No dobra, Redaktorka wcale nie mówiła, że dorzuci swojego Lexusa, może dlatego, że wcale się jej nie pytaliśmy. Ale w końcu jesteśmy zespołem i na pewno nie będzie z tym żadnych problemów.

Przynajmniej dopóki się nie dowie.

Uwaga Redaktorki: Redaktorka potrzebuje swojego Lexusa, żeby miała gdzie mieszkać po tym, jak ten artykuł zostanie odkryty.

Zapewne wielu z Was martwi się tą nieuchronnie zbliżającą się transakcją. Pewnie myślicie sobie: „Rety, jeśli Skrypciarze przejmą Yahoo!, będą wielcy i bogaci. Kiedy tak się stanie, nie będą chcieli poświęcać więcej swojego cennego czasu na pisanie skryptów administrowania systemem”. Wiecie co? Pewnie macie rację: zanim atrament na kontrakcie zdąży wyschnąć, będziemy już na plaży na Tahiti. Tymczasem, skoro jeszcze nie jesteśmy właścicielami Yahoo!, (przynajmniej jeszcze nie), możemy poświęcić chwile i odpowiedzieć na pytanie JS:

Const ForReading = 1

Const ForWriting = 2



Set objFSO = CreateObject("Scripting.FileSystemObject")

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



Do Until objFile.AtEndOfStream

    strLine1 = objFile.ReadLine

    If InStr(strLine1, "Medical") Then

        strDuplicateLine = strLine1

        strDuplicateLine = Replace(strDuplicateLine, "Medical", "Dental")

   End If

    strLine2 = objFile.ReadLine

    strLine3 = objFile.ReadLine

    strText = strText & strLine1 & vbCrLf & strLine2 & vbCrLf & strLine3 & vbCrLf

    

    If strDuplicateLine <> "" Then

        strText = strText & strDuplicateLine & vbCrLf & strLine2 & vbCrLf & strLine3 & vbCrLf

    End If



    strDuplicateLine = ""

Loop



objFile.Close



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

objFile.Write strText

objFile.Close

Zanim przejdę do opisywania funkcjonowania tego skryptu, spójrzmy na tekst, na którym pracujemy. JS ma plik tekstowy wyglądający tak:

Ken Myer, Medical, 1/1/1980

date, 1/1/2000

reference, 12345

Pilar Ackerman, None, 1/1/1980

date, 1/1/2000

reference, 12346

Jak widzimy, każde trzy wiersze w tekście reprezentują rekord dla określonej osoby: Wiersz 1 (do którego wrócę za chwilę) zawiera nazwisko osoby; wiersz 2 datę, a wiersz 3 numer referencyjny. Jeśli wiersz 1 zawiera także słowo Medical, będziemy chcieli skopiować ten rekord, ale z jednym wyjątkiem: w rekordzie powtarzającym się chcemy zastąpić słowo Dental słowem Medical. Innymi słowy, jeśli skrypt spełni swoje zadanie, zapis dotyczący Kena Myera powinien wyglądać tak:

Ken Myer, Medical, 1/1/1980

date, 1/1/2000

reference, 12345

Ken Myer, Dental, 1/1/1980

date, 1/1/2000

reference, 12345

Widzicie, jak to działa? A co się stanie z Pilar Ackerman? Nic. Ponieważ jej rekord nie zawiera słowa Medical, informacje się nie zmienią:

Pilar Ackerman, None, 1/1/1980

date, 1/1/2000

reference, 12346

Jasne? To dobrze. Teraz zobaczmy, czy jak nasz skrypt rozwiązuje to zadanie.

Na początek definiujemy parę stałych - ForReading oraz ForWriting – które wykorzystamy podczas otwierania pliku tekstowego. A skoro już o tym mowa, to jest następna rzecz, którą robimy: używamy poniższych dwóch wierszy kodu w celu utworzenia wystąpienia obiektu Scripting.FileSystemObject, a następnie otwieramy plik C:\Scripts\Test.txt do odczytu:

Set objFSO = CreateObject("Scripting.FileSystemObject")

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

Po otwarciu pliku zaczynamy sprawdzanie jego zawartości wiersz po wierszu. W tym celu uruchamiamy pętlę Do Until, która będzie działać, dopóki nie odczytamy każdego wiersza w pliku (lub, używając bardziej technicznego języka, dopóki wartość True właściwości AtEndOfStream pliku się nie zmieni):

Do Until objFile.AtEndOfStream

Wewnątrz tej pętli najpierw używamy metody ReadLine w celu odczytania pierwszego wiersza w pliku tekstowym i zachowujemy go w zmiennej o nazwie strLine1:

strLine1 = objFile.ReadLine

Teraz używamy funkcji InStr w celu stwierdzenia, czy słowo Medical pojawia się gdzieś w zmiennej strLine1:

If InStr(strLine1, "Medical") Then

Co się stanie, jeśli wiersz nie zawiera słowa Medical? Szczerze mówiąc nic. Ponieważ nie znajdujemy słowa Medical, nie ma nic szczególnego, co musielibyśmy zrobić z tym rekordem. Co innego, kiedy naprawdę znajdziemy słowo Medical. W takim przypadku musimy uruchomić poniższe dwa wiersze kodu:

strDuplicateLine = strLine1

        strDuplicateLine = Replace(strDuplicateLine, "Medical", "Dental")

Co tutaj robimy? Cóż, jak widać, niewiele. W wierszu 1 przypisujemy wartość zmiennej strLine1 do zmiennej o nazwie strDuplicateLine. W wyniku tego tworzymy wirtualną kopię pierwszego wiersza w pliku tekstowym. W wierszu 2 zastępujemy słowo Medical słowem Dental w zmiennej strDuplicateLine. Po wykonaniu tej czynności zmienna strLine będzie miała następującą wartość:

Ken Myer, Medical, 1/1/1980

Po chwili zmienna strLine będzie miała taką wartość:

Ken Myer, Dental, 1/1/1980

O to chodziło: mamy teraz pierwszy wiersz rekordu Medical Kena Myera oraz pierwszy wiersz jego rekordu Dental.

Przechodzimy do następujących dwóch wierszy kodu:

strLine2 = objFile.ReadLine

strLine3 = objFile.ReadLine

Oba te wiersze zasadniczo nie potrzebują wyjaśnień: w wierszu 1 używamy metody ReadLine w celu odczytania następnego wiersza w pliku tekstowym, a w wierszu 2 używamy tej samej metody w celu odczytania wiersza następującego po tym wierszu (trzeciego wiersza w pliku tekstowym). Wynik? Zmienna strLine2 będzie miała następującą wartość:

date, 1/1/2000

Zmienna strLine3 będzie miała wartość – cóż, macie rację - wiersza 3 w pliku tekstowym:

reference, 12345
Uwaga. Naprawdę to wiedzieliście, czy tylko zgadywaliście?

Mamy teraz wszystkie informacje potrzebne do utworzenia obydwu rekordów dla Kena Myera. (Lub po prostu przerobienia jednego rekordu, jeśli się okaże, że nie znaleźliśmy słowa Medical). Rekord 1 możemy utworzyć za pomocą następującego wiersza kodu:

strText = strText & strLine1 & vbCrLf & strLine2 & vbCrLf & strLine3 & vbCrLf

Przypisujemy tutaj nową wartość do zmiennej o nazwie strText. Ta wartość składa się z istniejącej wartości zmiennej strText plus następujące elementy:

  • Wartość zmiennej strLine1 ((Ken Myer, Medical, 1/1/1980) oraz znak powrotu karetki (stała vbCrLf skryptu VBScript).
  • Wartość zmiennej strLine2 (date, 1/1/2000) oraz następny znak powrotu karetki.
  • Wartość zmiennej strLine3 (reference, 12345) oraz jeszcze jeden znak powrotu karetki.

Innymi słowy, zmienna strText będzie miała następującą wartość:

Ken Myer, Medical, 1/1/1980

date, 1/1/2000

reference, 12345

Teraz sprawdzamy, czy zmienna strDuplicateLine ma wartość (czyli czy nie jest pustym ciągiem):

If strDuplicateLine <> "" Then

Jeśli zmienna strDuplicateLine ma wartość, może to oznaczać tylko jedno: znaleźliśmy słowo Medical w wierszu 1 tego rekordu, więc musimy dodać także rekord Dental. Do tego posłuży nam poniższy wiersz kodu:

strText = strText & strDuplicateLine & vbCrLf & strLine2 & vbCrLf & strLine3 & vbCrLf

Widzicie? W tym przypadku używamy zmiennej strDuplicateLine, w której zastąpiliśmy słowo Medical słowem Dental. Dzięki temu zmienna strText będzie miała następującą wartość:

Ken Myer, Medical, 1/1/1980

date, 1/1/2000

reference, 12345

Ken Myer, Dental, 1/1/1980

date, 1/1/2000

reference, 12345

I co Wy na to? Ken Myer ma teraz dwa rekordy – Medical oraz Dental – tak jak sobie tego życzyliśmy.

Po wykonaniu tych czynności resetujemy wartość zmiennej strDuplicateLine do pustego ciągu, a następnie wracamy na początek pętli w celu powtórzenia tego procesu dla następnego wiersza w pliku tekstowym. (Którym, jak sobie pewnie przypominacie, będzie wiersz 4 w pliku tekstowym. Odczytaliśmy już wiersz 1, 2 oraz 3). Po zakończeniu odczytywania całego pliku używamy metody Close w celu zamknięcia pliku Test.txt, a następnie używamy poniższego wiersza kodu w celu jego ponownego otwarcia, tym razem do zapisu:

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

Teraz używamy metody Write w celu zastąpienia istniejącej zawartości pliku wartością zmiennej strText, zamykamy plik po raz ostatni i tyle. Finito.

Jeżeli chodzi o ten kontrakt z Yahoo! muszę przyznać, że zaczynamy mieć pewne wątpliwości. Jak się okazuje, przeceniliśmy liczbę osób będących właścicielami akcji Yahoo!. Ta firma ma setki tysięcy akcjonariuszy, a nie 5 czy 6, jak się nam wydawało. Co to oznacza? To oznacza, że nie mamy wystarczającej liczby laleczek dr Scripto. Gdyby mogli się nimi podzielić, byłoby super. Albo mamy też inny pomysł: może firma Yahoo! kupi Centrum skryptów? W ten sposób mogłaby się odgryźć na Microsoft za tak marną ofertę. Tyko o tym pomyślcie: Mieć u siebie klejnot koronny firmy Microsoft – Centrum skryptów. Bezcenne.

Cóż, może nie do końca bezcenne. Skrypciarze są skłonni przyjąć 42 miliardy dolarów za Centrum skryptów. (Centrum skryptów jest pewnie warte wiele więcej, ale nie jesteśmy zachłanni). Możemy nawet osłodzić tę ofertę: jeśli kontrakt zostanie zawarty do końca miesiąca, dostaniecie 5% zniżki. Czekamy na odpowiedź.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne