giovedì 10 febbraio 2011

Come prendere l'output di un comando e impostarlo come variabile. - Lo Scriptomane - livello MEDIO

Buongiorno, ecco il secondo articolo di questo mio piccolo spazio dedicato allo scripting che promette di essere una guida per chi vuole dedicarsi ad un approccio innovativo per la gestione delle operazioni di amministrazione di computer, reti e quant'altro.

Al contrario del mio "cugino" americano: "the Scripting Guy", che ammiro molto e che è stato per me molte volte una guida, io cerco di non scomodare il signor VBScript quando non è proprio necessario.

Windows ha un cuore di scripting dalle potenzialità spesso inespresse / non documentate: il batch.

Oggi vedremo un argomento controverso a cui viene spesso data la risposta "non si può":
Come prendere l'output di un comando e impostarlo come variabile.

in batch si usa SET per impostare variabili ambiente (usate il comando SET senza parametri per visualizzare una lista completa di variabili ambiente presenti nel vostro PC, oppure "SET a" per vedere solo quelle che iniziano con a e via dicendo...).

il comando SET, come tutti gli altri comandi, può essere messo in un ciclo del comando FOR e il comando FOR è un tipo in gamba ad analizzare l’output dei comandi. Basta lanciare il comando che vogliamo analizzare dalle sue “parentesi”. Oggi vedremo anche un altro aspetto che di solito spinge gli scripters a redirigere l’output di comandi prima verso file di testo: il PIPING* all’interno del FOR mediante l’uso dei caratteri di ESCAPE*

Ma vediamo subito nella pratica.
Una delle operazioni più comuni che vorrebbero ottenere i sistemisti da un linguaggio di scripting è ottenere l’indirizzo IP del computer in uso, la sua netmask e il gateway predefinito. OK, mettete quanto segue in un file di batch:

@echo off
setlocal EnableDelayedExpansion
SET i=0
FOR /F "usebackq delims=: tokens=1,2,*" %%a IN (`IPCONFIG ^| FINDSTR /I "Indirizzo Subnet Gateway"`) DO (
set var!i!=%%b
SET /A i=!i!+1
)
echo var0: !var0!
echo var1: !var1!
echo var2: !var2!
pause
in var0 c'è l'IP, in var1 c'è la MASK, in var2 il gateway.

A questo punto urge una spiegazione, line by line, command by command:

@echo OFF -> evita che nell'output VISIVO, si vedano i comandi lanciati.

setlocal EnableDelayedExpansion -> Abilita l'espansione delle variabili all'interno del ciclo FOR (altrimenti sarebbero tutte VAR0 o VAR2 che si sovrascrivono, perchè le operazioni sulle variabili vengono eseguite tutte prima del ciclo FOR effettivo... un guazzabuglio: fidatevi di me). Quando si abilita questa caratteristica, le variabili vanno richiamate con !nomeVar! e non più con %nomeVar%. IMPORTANTE!

SET i=0 -> imposta la variabile %i% uguale a 0, ci servirà come "pezzo" del nome variabile.

... qui procedo più con calma
FOR /F "usebackq delims=: tokens=1,2,*" %%a ... -> qui diciamo al FOR di usare le estensioni dei comandi "usebackq", di analizzare l'input trovando i separatori ":" e di usare il primo valore prima di ":" come prima variabile, il secondo valore dopo i ":" come seconda (%%b, perchè va in ordine alfabetico) e, se anche trovasse un terzo ":" e un quarto ":", tutto ciò che viene dopo il terzo ":" come terza variabile.

... IN (`IPCONFIG ^| FINDSTR /I "Indirizzo Subnet Gateway"`) DO ( -> qui dico al comando FOR di analizzare riga per riga dell'output del comando incluso in apici inversi " ` " (si ottengono con il codice ASCII 96, quindi: tengo premuto ALT e scrivendo 96, poi rilascio ALT e "appare magicamente").
Il comando che inserisco dovrebbe essere IPCONFIG | FINDSTR /I "Indirizzo Subnet Gateway" OVVERO: passo l'output del comando ipconfig al comando FINDSTR, dicendo che mi estragga SOLO le righe che contengono "Indirizzo", "Subnet" oppure "Gateway". Però il PIPING mi manderebbe in errore il comando FOR, se non fosse ESCAPED dal carattere ^. Infatti l'interprete BATCH analizzerebbe la richiesta come "tutto quello che si trova prima del PIPE è il primo comando sulla riga, tutto ciò che si trova dopo il secondo. Il comando terminerebbe con un erroraccio ininterpretabile: " %%a non atteso. ". :-)

Tutte le righe che seguono la parentesi aperta e che precedono la parentesi chiusa sono eseguite ciclicamente dal FOR, quindi per ogni riga dell'output del comando sopra descritto.

SET var!i!=%%b -> qui dico di impostare la variabile varX (dove X è il valore attuale della variabile !i! che abbiamo inizializzato prima del FOR e che al primo ciclo è 0) con la SECONDA variabile nell'analisi di FOR della riga, ovvero tutto ciò che è successivo al primo ":" della riga analizzata.

SET /A i=!i!+1 ->incremento la variabile !i! algebricamente (/A) di uno rispetto al suo valore attuale.

ed ecco spiegato il "trucco". Spero che vi sia utile in futuro! :-)


P.S.: problemi con gli spazi? non li volete? usate le sostituzioni. Es. !var0: =! ritornerà la variabile var0 senza spazi (spazio uguale niente).

--
Diego Castelli
Verona - Italy
-------------------------
MCSA 2003, MCTS Forefront, MCP
HP AIS, HP APS

Nessun commento:

Posta un commento

I commenti sono soggetti a moderazione, prima di essere pubblicati.

Qualsiasi contenuto illecito, immorale o che io ritenga (arbitrariamente) offensivo od inappropriato, verrà cancellato.