Centrum Skryptów - Systemy Operacyjne

Jak zastąpić tekst zawierający podwójne cudzysłowy i znak tabulacji?

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 zastąpić tekst zawierający podwójne cudzysłowy i znak tabulacji?

Cześć, Skrypciarze! Jeden z Waszych artykułów na temat zastępowania tekstu w pliku okazał się bardzo przydatny. Potrzebowałbym jednak czegoś bardziej zaawansowanego: chciałbym zastąpić tekst zawierający podwójne cudzysłowy i znak tabulacji. Jak to zrobić?

-- FC

Cześć, FC! Po Twoim pytaniu mniemam, że czytałeś już kiedyś jakiś artykuł z serii „Cześć, Skrypciarze!”. Zauważyłeś więc na pewno, że dzielę się na łamach dość osobistymi spostrzeżeniami, których, niestety, nikt nie podziela. O jakiego typu spostrzeżenia chodzi mi obecnie? No na przykład karty rabatowe w sklepach spożywczych. Nie wiem na ile Ty, FC, obeznany jesteś z tym procederem, ale w Stanach jest to bardzo popularne. Kupując w danym sklepie okazujesz kartę rabatową i… dostajesz rabat. Czy mam coś przeciwko rabatom? Oczywiście, że nie mam, nie podoba mi się jednak fakt, że sklep wie co kupuję i w jakich ilościach. Zakupy są przecież sprawą dość osobistą i nie chcę doczekać czasów, kiedy informacja na temat co i gdzie kupuję będzie dostępna online.

Na szczęście tajność informacji nie dotyczy pytań na temat zastępowania tekstu zawierającego podwójne cudzysłowy i znak tabulacji. Takiej informacji udzielamy publicznie i może dorzucimy coś jeszcze w formie rabatu…

Z tego co napisałeś, FC, wynika, że masz plik (lub kilka plików), które zawierają tekst, w którym podkreślnik oznacza znak tabulacji:

rowsep="1">_

Ty natomiast chciałbyś zastąpić te wartości następującymi:

rowsep="1"><para>

Napotykam tu jednak mały problem, a w sumie dwa. Po pierwsze: podwójne cudzysłowy w ciągu docelowym, po drugie: znak tabulacji pod koniec tego ciągu. Jak wyszukać tekst zawierający podwójny cudzysłów i znak tabulacji? No cóż, jest jeden sposób:

Const ForReading = 1

Const ForWriting = 2



Set objFSO = CreateObject("Scripting.FileSystemObject")

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



strText = objFile.ReadAll

objFile.Close



strTargetText = "rowsep=" & Chr(34) & "1" & Chr(34) & ">" & vbTab

strReplacementText = "rowsep=" & Chr(34) & "1" & Chr(34) & "><para>"



strNewText = Replace(strText, strTargetText, strReplacementText)



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

objFile.WriteLine strNewText

objFile.Close

Zobaczmy, czy jesteśmy w stanie wytłumaczyć, jak działa nasz skrypt. Jak widać, zaczynamy w sposób dość standardowy – od zdefiniowania pary stałych ForReading oraz ForWriting. Będziemy używać ich do otwierania naszych plików tekstowych – stałej ForReading do otworzenia pliku i przeczytania zawartości, a następnie stałej ForWriting do ponownego otworzenia pliku zmiany pierwotnej zawartości na wartość docelową.

Uwaga: Może to i wydaje się głupie, że nie możemy zmodyfikować pliku przy użyciu jednej operacji, tylko trzeba go otworzyć, wpisać zawartość do pamięci, następnie zamknąć plik. I to nie wszystko. Po dokonaniu zmian w kopii roboczej musimy ponownie otworzyć plik i zastąpić zawartość pierwotną naszą kopią roboczą.

Po zdefiniowaniu naszych dwóch stałych, tworzymy wystąpienie obiektu Scripting.FileSystemObject, a następnie używamy poniższego wiersza kodu w celu otworzenia pliku C:\Scripts\Test.txt do odczytu:

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

Po otworzeniu pliku korzystamy z metody ReadAll w celu sczytania całej zawartości pliku, przechowując jego zawartość w zmiennej strText. Po sczytaniu pliku wywołujemy metodę Close (bez obaw, wspominaliśmy przecież, że w odpowiednim czasie tworzymy plik po raz kolejny).

To wszystko sprowadza nas do następujących dwóch wierszy kodu:

strTargetText = "rowsep=" & Chr(34) & "1" & Chr(34) & ">" & vbTab

strReplacementText = "rowsep=" & Chr(34) & "1" & Chr(34) & "><para>"

Wygląda strasznie, przyznaję, nie taki diabeł jednak straszny jak go malują. W pierwszym wierszu po prostu definiujemy tekst, który chcemy wyszukać, a jak dobrze pamiętacie wygląda on następująco:

rowsep="1">_

Pracowanie z takim tekstem może być niezmiernie… hmm… ciekawe. Dopóki nie spróbujesz, możesz jeszcze się łudzić, że można po prostu przypisać tę wartość zmiennej przy użyciu następującego kodu:

strTargetText = "rowsep="1">     "

Teraz nie jest to już ciekawe, ale frustrujące, ponieważ odkrywasz, że takiej operacji nie można po prostu wykonać, a to z dwóch następujących powodów:

  • Problemów nastręczają podwójne cudzysłowy wewnątrz ciągu. Dlaczego? Ponieważ VBScript używa tych znaków w celu zaznaczenia początku i końca ciągu. Dlatego też dla VBScript naszym ciągiem jest: "rowsep=". Po odkryciu kolejnych cudzysłowów skrypt głupieje i następuje błąd.
  • Podczas przypisywania wartości do ciągu znakowego tak naprawdę znak tabulacji nie zostaje przypisany – w jego miejsce przypisanych zostaje pięć spacji. Wyglądają może i tak samo, ale to tylko pozory.

Innymi słowy, aby przypisać tekst docelowy zmiennej strTargetText, musimy oba te problemy jakoś obejść. Nasze rozwiązanie składa się z czterech składowych ciągu:

  • rozpoczęcia podwójnym cudzysłowem (").
  • Wartości ciągu rowsep=.
  • Funkcji Chr(34). Chr(34) to właściwie reprezentacja podwójnego cudzysłowu w ASCII. Oznacza to, że dodajemy po prostu Chr(34) do naszego ciągu, bez potrzeby wpisywania podwójnego cudzysłowu. Omijamy tym samym problem związany z umieszczaniem jednego cudzysłowu w drugim (tak, istnieją również inne sposoby na umieszczanie cudzysłowu w cudzysłowie, ten jednak jest najprostszy).
  • Wartości ciągu 1.
  • Kolejnego wystąpienia Chr(34). Innymi słowy, kolejny zestaw podwójnych cudzysłowów.
  • Wartości ciągu >.
  • Znaku tabulacji, który w VBScript ma stałą vbTab. Nie musimy przypominać, że nasz ciąg zawiera znak tabulacji. Pamiętajcie więc, żeby nie dodawać go za pomocą klawisza TAB, ale za pomocą vbTab.
  • Zamykający cudzysłów (").

Bardziej wizualnie, z podkreślnikiem w roli znaku tabulacji oraz prawdziwymi cudzysłowami w miejsce wartości Chr(34):

"

+     rowsep=

+            "

+             1

+              "

+               >

+                _

+                 "

_____________________



     "rowsep="1">_"

Dzisiejszy skrypt, jak sami widzicie, sponsorują literki Chr(34) oraz vbTab.

Po skonstruowaniu naszego ciągu przypisujemy jego wartość zmiennej strTargetText, a następnie korzystamy z podobnego podejścia w celu skonstruowania tekstu zastępczego:

strReplacementText = "rowsep=" & Chr(34) & "1" & Chr(34) & "><para>"

Jedyną różnicą jest tu, że na końcu mamy nie znak tabulacji, ale wartość ciągu <para>.

Uwaga: Czy nie łatwiej byłoby wyszukać wszystkie znaki tabulacji i zastąpić je ciągiem <para>? Tak, ale tylko jeżeli chcielibyśmy zastąpić wszystkie znaki tabulacji, a z tego, co napisał FC, wnioskuję, że chodziło mu o jakieś konkretne znaki tabulacji (które występują po rowsep="1"). Właśnie dlatego skorzystaliśmy z tego bardziej skomplikowanego, ale i pewniejszego sposobu.

Po zdefiniowaniu naszego tekstu docelowego i tekstu, którym mamy go zastąpić, wystarczy już tylko wywołać funkcję Replace:

strNewText = Replace(strText, strTargetText, strReplacementText)

To polecenie wyszuka wystąpienia tekstu docelowego dla wartości strText, a następnie je zastąpi. Po dokonaniu tego, nasz zmodyfikowany plik tekstowy (lub przynajmniej nasza kopia robocza tego pliku tekstowego) zostanie przypisany zmiennej strNewText.

Oczywiście zmodyfikowaliśmy tu tylko kopię roboczą. W celu zmodyfikowania tekstu właściwego musimy skorzystać z następującego fragmentu kodu:

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

objFile.WriteLine strNewText

objFile.Close

W pierwszym wierszu otwieramy ponownie plik C:\Scripts\Test.txt, tym razem do zapisu. W drugim wierszu przechodzimy do właściwego zapisywania, korzystając z WriteLine (przypisujemy wartość naszego zmodyfikowanego pliku roboczego strNewText zmiennej Test.txt. W końcu, w trzecim wierszu, wywołujemy metodę Close i zamykamy plik. Teraz już naprawdę skończyliśmy, a tekst docelowy w pliku Test.txt został również zamieniony.

Obiecywałem w sumie jakiś rabat, ale artykuł jest już dość długi, rabatem może będzie więc nie dodawanie już niczego i pozwolenie Ci, FC, spokojnie pójść na zakupy… Uważaj tylko z kartami rabatowymi. Wielki brat czuwa…

 Do początku strony Do początku strony

Centrum Skryptów - Systemy Operacyjne