Tutti i programmatori hanno avuto a che fare con operazioni di cerca/sostituisci nel testo, e di utilities per questo tipo di operazioni, in effetti ce ne sono parecchie. Gli utenti Linux hanno a disposizione molti strumenti nativi potenti e flessibili, chi utilizza Windows invece, sebbene possa installare linguaggi di script di terze parti come Perl o PHP, se vuole utilizzare strumenti nativi deve utilizzare VBScript e Windows Script Host (WSH). Per essere precisi, non è del tutto necessario conoscere VBScript, perché la piattaforma WSH è language-indipendent, dunque altri linguaggi come javascript sono pure supportati.
Fatta questa piccola premessa, torniamo al tema delle sostituzioni nel testo. Ho trovato su Internet numerosi script per la ricerca e la sostituzione di testo sia in un unico file che in file multipli (problema comune per i webmaster), ma non ho trovato molto per poter sostituire velocemente una lunga lista di stringhe, con un’altra all’interno di un certo file di testo. Un esempio pratico potrebbe essere un file CSV che contiene una colonna di codici da sostituire con la corrispettiva lista di id estratta dalla tabella di un database. Questo processo potrebbe risultare utile per velocizzare l’importazione di certi dati in tabelle di database.
Ho assemblato questo piccolo script VBScript utilizzando porzioni di codice reperite nella rete, ed aggiungendo alcune personalizzazioni.
Queste sono le caratteristiche:
- Lo script carica da un file CSV che utilizza la “,” come separatore, un array di stringhe da cercare e il corrispettivo array di stringhe sostitutive
- Apre il file con il testo da elaborare ed effettua le sostituzioni
- Salva il testo modificato in un nuovo file in modo da preservare l’originale
Ecco il codice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | ' VB Script Document option explicit Dim FileName, FileContents, dFileContents, FileFindReplace Dim oFSO, oTextFile, arrList, items, keys Dim sNextLine, tmp, i FileName = WScript.Arguments(0) FileFindReplace = WScript.Arguments(1) 'Read source text file FileContents = GetFile(FileName) dFileContents = FileContents Set oFSO = CreateObject("Scripting.FileSystemObject") Set oTextFile = oFSO.OpenTextFile(FileFindReplace, 1) Set arrList = CreateObject("Scripting.Dictionary") Do Until oTextFile.AtEndOfStream sNextLine = oTextFile.Readline tmp = Split(sNextLine , ",") arrList.Add tmp(0), tmp(1) Loop items = arrList.Items keys = arrList.Keys 'Loop through Items array For i = 0 To UBound(items) 'replace all string In the source file dFileContents = replace(dFileContents, items(i), keys(i), 1, -1, 1) Next 'Compare source And result if dFileContents <> FileContents Then 'write result If different WriteFile NewFileName(FileName), dFileContents Wscript.Echo "Replace done." Else Wscript.Echo "Searched string Not In the source file" End If 'Read text file Function GetFile(FileName) If FileName<>"" Then Dim FS, FileStream Set FS = CreateObject("Scripting.FileSystemObject") on error resume Next Set FileStream = FS.OpenTextFile(FileName) GetFile = FileStream.ReadAll End If End Function 'Write string As a text file. Function WriteFile(FileName, Contents) Dim OutStream, FS on error resume Next Set FS = CreateObject("Scripting.FileSystemObject") Set OutStream = FS.OpenTextFile(FileName, 2, True) OutStream.Write Contents End Function 'Compose new file name with date and time. Function NewFileName(sFileName) Dim MyDate, arrNewFileName, sNewFileName, sExt arrNewFileName = Split(sFileName, "\") sNewFileName = arrNewFileName(Ubound(arrNewFileName)) MyDate = Replace(Now, "/", "") MyDate = Replace(MyDate, ".", "") MyDate = Replace(MyDate, " ", "_") If InStr(sNewFileName, ".") Then sExt = Right(sNewFileName, 3) sNewFileName = Left(sNewFileName,(Len(sNewFileName) - 4)) sNewFileName = sNewFileName & "_" & MyDate & "." & sExt Else sNewFileName = sNewFileName & "_" & MyDate End If NewFileName = sNewFileName End Function |
Vediamo la sua applicazione in un file di prova (prova.txt) che contiene il seguente testo:
uno due due tre tre quattro cinque cinque sei sette otto otto nove dieci dieci dieci dieci
nel quale vogliamo convertire le stringhe in numeri (per fare questo in realtà ci sarebbero anche altri metodi più veloci!)
Il file per le sostituzioni (decodificaprova.txt) sarà
1,uno 2,due 3,tre 4,quattro 5,cinque 6,sei 7,sette 8,otto 9,nove 10,dieci
lanciamo lo script che chiameremo find_replace.vbs, indicando come primo parametro il file su cui effettuare le sostituzioni e come secondo parametro il file di decodifica: C:\percorso_del_file\find_replace.vbs" prova.txt decodificaprova.txt
Il risultato (in questo caso: prova_18052008_104851.txt) prende il nome del file originale + una stringa che rappresenta la data e l’ora di sistema:
1 2 2 3 3 4 5 5 6 7 8 8 9 10 10 10 10
NOTE:
Il file di decodifica deve avere una prima colonna con l’elenco delle sostituzioni ed una seconda colonna con l’elenco delle stringhe da ricercare. E’ molto importante evitare stringhe ambigue, ad esempio se si vuole sostituire l’articolo “la” con “una” e nel testo esiste la parola “lana”, questa verrà convertita in “unana”! In questi casi è bene inserire dei delimitatori come ad esempio il carattere #
Requisiti:
E’ necessario che sia installato il supporto WSH, la versione più recente è la 5.7
Conclusioni:
Lo script si è rivelato molto veloce ed efficiente, sarebbe interessante migliorarlo per ottenere una maggiore flessibilità e sicurezza, ma il suo scopo era quello di risolvere velocemente un problema che mi avrebbe fatto perdere molto tempo se affrontato manualmente, e lo ha raggiunto!
Riferimenti ed approfondimenti: