Centrum Skryptów - Systemy Operacyjne

Jak wykorzystać powłokę Windows PowerShell do zastąpienia znaków w pliku tekstowym?

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 wykorzystać powłokę Windows PowerShell do zastąpienia znaków w pliku tekstowym?

Cześć, Skrypciarze! Jak za pomocą powłoki Windows PowerShell zastąpić wszystkie znaki gwiazdki znajdujące się w pliku tekstowym innym znakiem?

-- RC

Cześć, RC. Czy wiecie, że mnóstwo osób pyta mnie często, jak to robię, że udaje mi się napisać nowy artykuł każdego dnia. Oczywiście wiele osób pyta też, po co w ogóle piszę te artykuły, ale to już inna historia. Zastanawiają się czy mnie to nie męczy, nie nudzi ani nie powoduje żadnych chorób.

Możecie wierzyć lub nie, ale odpowiedz na to pytanie brzmi: nie. Nigdy mnie to jeszcze nie zmęczyło ani nie znudziło. Nigdy też przez to nie zachorowałem; tak naprawdę to jestem prawdopodobnie najzdrowszą osobą na tym świecie. Czy to z powodu rygorystycznego programu dietetyczno-gimnastycznego? Niezupełnie, chyba że oglądanie TV można uznać za sport, a pączki za podstawę zdrowej diety. Ja tryskam zdrowiem z innego powodu: jestem przepracowany i zestresowany.

To prawda: stres związany z pracą jest dla nas dobry. Naukowcy z Europy odkryli niedawno, że ludzie łatwiej zapadają na jakąś chorobę, kiedy są na wakacjach, niż kiedy codziennie chodzą do pracy. Ci naukowcy twierdzą, że jest tak dlatego, iż stresory w miejscu pracy uruchamiają mechanizmy obronne organizmu, co ułatwia mu odpieranie chorób i infekcji. Kiedy relaksujemy się w domu, organizm nie jest już taki czujny i zanim się obejrzymy, łapiemy przeziębienie lub grypę. Zdrowie potrzebuje stresorów z miejsca pracy.

To dla mnie bardzo dobra wiadomość. W końcu, jeżeli stresory z miejsca pracy wpływają pozytywnie na nasze zdrowie, to ja chyba będę żył 190 lat. I jeszcze długo popracuję.

Biorąc pod uwagę fakt, że cały ranek spędziłem przygotowując się do zimowej Olimpiady skrypciarskiej (j.ang.), czuję się dziś szczególnie zdrowo. Zobaczmy, czy uda nam się wykombinować, jak użyć powłoki Windows PowerShell w celu zastąpienia znaków w pliku tekstowym. Załóżmy, że mamy następujący plik tekstowy (C:\Scripts\Test.txt):

This is line 1.*

This is line 2*.

*This is line 3.

This is * line 4.

Załóżmy ponadto (z pewnego powodu), że chcemy zastąpić te nieznośne gwiazdki (*) znakami małpy (@). Jak to zrobić? Oto skrypt, który powinien załatwić sprawę:

(Get-Content C:\Scripts\Test.txt) | 

Foreach-Object {$_ -replace "\*", "@"} | 

Set-Content C:\Scripts\Test.txt

Jak widzimy, nie ma wiele do powiedzenia na temat tego skryptu; gdybyśmy mieli odrobinę szersze strony, umieścilibyśmy wszystko w jednym wierszu. Zaczynamy od zastosowania cmdletu Get-Content w celu wczytania tekstu z pliku tekstowego C:\Scripts\Test.txt; domyślnie tekst zostaje wpisany jako tablica, w której każdy element reprezentuje jeden wiersz w pliku tekstowym. Zauważcie, że polecenie Get-Content zostało umieszczone w nawiasach. W jakim celu? Ponieważ w ten sposób możemy być pewni, że powłoka PowerShell wczyta całą zawartość pliku, zanim zdąży zrobić cokolwiek innego.

Co się zatem dzieje po wczytaniu całej zawartości pliku tekstowego przez PowerShell? Cóż, naszym następnym krokiem jest dodanie tej zawartości do cmdletu Foreach-Object. Jak już mówiłem, kiedy powłoka PowerShell wczyta zawartość pliku tekstowego, automatycznie zamienia te informacje na tablicę. Cmdlet Foreach-Object uruchomi teraz pętlę, która przejdzie przez każdy element w tablicy; innymi słowy, przejdzie przez każdy wiersz w pliku tekstowym. I dla każdego z tych wierszy polecenie Foreach-Object wykona następujący fragment kodu:

{$_ -replace "\*", "@"}

Jak zapewne wiecie, w potoku Windows PowerShell ciąg $_ reprezentuje bieżący obiekt. W tym przypadku przy pierwszym przejściu pętli $_ reprezentuje pierwszy wiersz w pliku tekstowym; przy drugim przejściu pętli $_ będzie reprezentować drugi wiersz w pliku tekstowym i tak dalej. Dla każdego z tych wierszy (czyli dla każdej wartości ciągu) użyjemy metody Replace w celu zastąpienia wszystkich gwiazdek w tym wierszu znakiem @. W tym celu określamy docelowy znak (gwiazdkę) z następującym po niej tekstem zastępującym (znakiem @).

Jedynym haczykiem tutaj jest fakt, że gwiazdka jest w powłoce Windows PowerShell znakiem zarezerwowanym; dlatego też musimy ten znak oznaczyć, zanim będziemy go mogli wyszukać i zastąpić. Czy to trudne? Wcale nie. Musimy po prostu poprzedzić znak gwiazdki (podobnie, jak każdy inny znak zarezerwowany) znakiem \:

"\*"

I jeszcze jedno, to ważne. Jeżeli pominiemy ukośnik, przy każdym przejściu pętli wyświetli nam się poniższy komunikat o błędzie:

Invalid regular expression pattern: *.

At C:\scripts\test.ps1:2 char:33

+ Foreach-Object {$_ -replace "*",  <<<< "@"} |

Oczywiście należy mieć na uwadze, że jedynym powodem, dla którego musimy oznaczyć znak gwiazdki jest fakt, że jest to znak zarezerwowany w wyrażeniach regularnych. Jeżeli chcemy wyszukać coś, co nie jest znakiem zarezerwowanym, należy pominąć ukośnik:

{$_ -replace "a", "@"}

Zatem, innymi słowy, czasami znak „\” jest nam potrzebny, a czasem wręcz przeciwnie. Skąd mamy wiedzieć, kiedy jest potrzebny, a kiedy nie? Rety, nie utrudniajcie mi życia.

Nie martwcie się tym; stres jest dla Was dobry (powinienem chyba powiedzieć: „martwcie się, ile chcecie”, w końcu martwić się to znaczy stresować). Nie usicie pamiętać, które znaki są znakami zarezerwowanymi. Ja Wam powiem. Nie jestem pewien, czy poniższa lista (pobrana z MSDN) jest kompletna, ale to dobry początek:

  • $
  • ( )
  • *
  • +
  • .
  • [ ]
  • ?
  • \
  • /
  • ^
  • { }
  • |

OK, wróćmy teraz do naszego skryptu. Kiedy Foreach-Object zakończy znajdowanie i zamienianie, nasz wirtualny plik tekstowy zostanie przekazany do polecenia cmdlet Set-Content. Z kolei polecenie Set-Content wpisuje zmodyfikowane dane z powrotem do pliku C:\scripts\Test.txt:

Set-Content C:\Scripts\Test.txt

I to wszystko. Koniec naszej pracy.

Rzeczywiście, macie rację: to wyglądało na zbyt proste. Spójrzmy zatem na plik Test.txt i zobaczmy, co się z nim dzieje:

This is line 1.@

This is line 2@.

@This is line 3.

This is @ line 4.

Cóż, to naprawdę było proste.

 Do początku strony Do początku strony

Centrum Skryptów - Systemy Operacyjne