Abbiamo eseguito esperimenti per studiare la grammatica degli script batch. Abbiamo anche studiato le differenze tra la modalità batch e la riga di comando.
Analizzatore di linee batch:
Ecco una breve panoramica delle fasi nel parser della riga del file batch:
Fase 0) Leggi la riga:
Fase 1) Espansione percentuale:
Fase 2) Elaborazione di caratteri speciali, tokenizzazione e creazione di un blocco comandi memorizzato nella cache: si tratta di un processo complesso che è influenzato da elementi quali virgolette, caratteri speciali, delimitatori di token e escape del cursore.
Fase 3) Eco il / i comando / i analizzato / i Solo se il blocco comandi non è iniziato @
e ECHO era ON all'inizio del passaggio precedente.
Fase 4) %X
Espansione variabile FOR : solo se è attivo un comando FOR e vengono elaborati i comandi dopo DO.
Fase 5) Espansione ritardata: solo se è abilitata l'espansione ritardata
Fase 5.3) Elaborazione del tubo: solo se i comandi sono su entrambi i lati di un tubo
Fase 5.5) Eseguire il reindirizzamento:
Fase 6) Elaborazione CHIAMATA / Raddoppio del cursore: solo se il token di comando è CHIAMATA
Fase 7) Esegui: il comando viene eseguito
Ecco i dettagli per ogni fase:
Si noti che le fasi descritte di seguito sono solo un modello di come funziona il parser batch. Gli interni effettivi di cmd.exe potrebbero non riflettere queste fasi. Ma questo modello è efficace nel prevedere il comportamento degli script batch.
Fase 0) Leggi riga: leggi prima la riga di input <LF>
.
- Quando si legge una riga da analizzare come comando,
<Ctrl-Z>
(0x1A) viene letto come<LF>
(LineFeed 0x0A)
- Quando GOTO o CALL legge linee durante la scansione di: etichetta,
<Ctrl-Z>
è così trattato stessa - è non convertito<LF>
Fase 1) Espansione percentuale:
- Una doppia
%%
è sostituita da una singola%
- Espansione di argomenti (
%*
, %1
,%2
, etc.)
- Espansione di
%var%
, se var non esiste sostituirlo con nulla
- La linea viene inizialmente troncata
<LF>
non all'interno %var%
dell'espansione
- Per una spiegazione completa leggi la prima metà di questo da dbenham Stesso thread: Fase percentuale
Fase 2) Elaborazione di caratteri speciali, tokenizzazione e creazione di un blocco comandi memorizzato nella cache: si tratta di un processo complesso che è influenzato da elementi quali virgolette, caratteri speciali, delimitatori di token e escape del cursore. Ciò che segue è un'approssimazione di questo processo.
Ci sono concetti importanti durante questa fase.
- Un token è semplicemente una stringa di caratteri che viene trattata come un'unità.
- I token sono separati da delimitatori token. I delimitatori di token standard sono
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
e<0xFF>
delimitatori di token consecutivi vengono considerati come uno - non ci sono token vuoti tra i delimitatori di token
- Non ci sono delimitatori di token all'interno di una stringa tra virgolette. L'intera stringa tra virgolette viene sempre trattata come parte di un singolo token. Un singolo token può consistere in una combinazione di stringhe tra virgolette e caratteri non quotati.
I seguenti caratteri possono avere un significato speciale in questa fase, a seconda del contesto: <CR>
^
(
@
&
|
<
>
<LF>
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
<0xFF>
Guarda ogni personaggio da sinistra a destra:
- Se
<CR>
quindi rimuoverlo, come se non fosse mai stato lì (tranne per il comportamento strano reindirizzamento )
- Se un punto di inserimento (
^
), il carattere successivo viene evaso e il punto di escape viene rimosso. I caratteri di escape perdono tutto il significato speciale (tranne che per <LF>
).
- Se un preventivo (
"
), attiva o disattiva la bandiera del preventivo. Se il flag di citazione è attivo, solo "
e <LF>
sono speciali. Tutti gli altri personaggi perdono il loro significato speciale fino a quando la citazione successiva disattiva la bandiera della citazione. Non è possibile sfuggire alla citazione di chiusura. Tutti i caratteri tra virgolette sono sempre all'interno dello stesso token.
<LF>
disattiva sempre la bandiera del preventivo. Altri comportamenti variano a seconda del contesto, ma le virgolette non modificano mai il comportamento di <LF>
.
- Sfuggito
<LF>
<LF>
è spogliato
- Il personaggio successivo è fuggito. Se alla fine del buffer di riga, la riga successiva viene letta ed elaborata dalle fasi 1 e 1.5 e aggiunta a quella corrente prima di sfuggire al carattere successivo. Se il personaggio successivo è
<LF>
, allora viene trattato come un valore letterale, il che significa che questo processo non è ricorsivo.
<LF>
Non sfuggito tra parentesi
<LF>
viene rimosso e l'analisi della riga corrente viene terminata.
- Eventuali caratteri rimanenti nel buffer di riga vengono semplicemente ignorati.
- Senza caratteri
<LF>
di escape all'interno di un blocco tra parentesi FOR IN
<LF>
viene convertito in a <space>
- Se alla fine del buffer di riga, la riga successiva viene letta e aggiunta a quella corrente.
- Senza caratteri
<LF>
di escape all'interno di un blocco comandi tra parentesi
<LF>
viene convertito in <LF><space>
e <space>
viene trattato come parte della riga successiva del blocco comandi.
- Se alla fine del buffer di riga, la riga successiva viene letta e aggiunta allo spazio.
- Se uno dei caratteri speciali
&
|
<
o >
, dividere la linea in questo punto per gestire le pipe, comandare la concatenazione e il reindirizzamento.
- Nel caso di un tubo (
|
), ogni lato è un comando separato (o blocco comandi) che ottiene una gestione speciale nella fase 5.3
- Nel caso di
&
, &&
o ||
concatenazione di comandi, ciascun lato della concatenazione viene trattato come un comando separato.
- Nel caso di
<
, <<
, >
, o >>
il reindirizzamento, la clausola reindirizzamento viene analizzato, temporaneamente rimosso, e poi aggiunto alla fine del comando corrente. Una clausola di reindirizzamento è costituita da una cifra di gestione del file facoltativa, dall'operatore di reindirizzamento e dal token di destinazione del reindirizzamento.
- Se il token che precede l'operatore di reindirizzamento è una singola cifra senza escape, la cifra specifica l'handle del file da reindirizzare. Se il token handle non viene trovato, l'output predefinito reindirizza su 1 (stdout) e l'input reindirizza su 0 (stdin).
- Se il primo token per questo comando (prima di spostare il reindirizzamento alla fine) inizia con
@
, allora @
ha un significato speciale. ( @
non è speciale in nessun altro contesto)
- Lo speciale
@
è stato rimosso.
- Se ECHO è ON, questo comando, insieme a tutti i seguenti comandi concatenati su questa linea, sono esclusi dall'eco della fase 3. Se il
@
è prima di un'apertura (
, l'intero blocco tra parentesi viene escluso dall'eco della fase 3.
- Parentesi di processo (fornisce istruzioni composte su più righe):
- Se il parser non è alla ricerca di un token di comando,
(
non è speciale.
- Se il parser è alla ricerca di un token di comando e trova
(
, quindi avviare una nuova istruzione composta e incrementare il contatore tra parentesi
- Se il contatore parentesi è> 0,
)
termina l'istruzione composta e decrementa il contatore parentesi.
- Se viene raggiunta la fine della linea e il contatore delle parentesi è> 0, la riga successiva verrà aggiunta all'istruzione composta (ricomincia dalla fase 0)
- Se il contatore tra parentesi è 0 e il parser è alla ricerca di un comando,
)
funziona in modo simile a REM
un'istruzione fintanto che è immediatamente seguito da un delimitatore di token, un carattere speciale, una nuova riga o una fine del file
- Tutti i caratteri speciali perdono il loro significato tranne
^
(la concatenazione di righe è possibile)
- Una volta raggiunta la fine della linea logica, l'intero "comando" viene scartato.
- Ogni comando viene analizzato in una serie di token. Il primo token viene sempre trattato come un token di comando (dopo che lo speciale
@
è stato rimosso e il reindirizzamento viene spostato alla fine).
- I delimitatori di token iniziali prima del token di comando vengono eliminati
- Durante l'analisi del token di comando,
(
funziona come delimitatore di token di comando, oltre ai delimitatori di token standard
- La gestione dei token successivi dipende dal comando.
- La maggior parte dei comandi concatena semplicemente tutti gli argomenti dopo il token di comando in un singolo token argomento. Tutti i delimitatori di token argomento vengono conservati. Le opzioni dell'argomento non vengono in genere analizzate fino alla fase 7.
- Tre comandi ottengono una gestione speciale: IF, FOR e REM
- IF viene suddiviso in due o tre parti distinte che vengono elaborate in modo indipendente. Un errore di sintassi nella costruzione IF provocherà un errore fatale di sintassi.
- L'operazione di confronto è il comando effettivo che scorre fino alla fase 7
- Tutte le opzioni di IF sono analizzate completamente nella fase 2.
- I delimitatori di token consecutivi vengono compressi in un unico spazio.
- A seconda dell'operatore di confronto, ci saranno uno o due token valore identificati.
- Il vero blocco di comandi è l'insieme di comandi dopo la condizione e viene analizzato come qualsiasi altro blocco di comandi. Se si deve utilizzare ELSE, il blocco True deve essere tra parentesi.
- Il blocco di comandi False opzionale è l'insieme di comandi dopo ELSE. Ancora una volta, questo blocco comandi viene analizzato normalmente.
- I blocchi di comando Vero e Falso non scorrono automaticamente nelle fasi successive. La loro successiva elaborazione è controllata dalla fase 7.
- FOR viene diviso in due dopo il DO. Un errore di sintassi nella costruzione FOR comporterà un errore di sintassi fatale.
- La parte attraverso DO è l'effettivo comando FOR iteration che scorre fino alla fase 7
- Tutte le opzioni FOR sono completamente analizzate nella fase 2.
- La clausola tra parentesi IN considera
<LF>
come <space>
. Dopo aver analizzato la clausola IN, tutti i token vengono concatenati insieme per formare un singolo token.
- I delimitatori di token consecutivi senza escape / non quotati vengono compressi in un unico spazio nel comando FOR tramite DO.
- La parte dopo DO è un blocco comandi che viene analizzato normalmente. La successiva elaborazione del blocco comandi DO è controllata dall'iterazione nella fase 7.
- Il REM rilevato nella fase 2 viene trattato in modo drammatico diverso rispetto a tutti gli altri comandi.
- Viene analizzato solo un token argomento: il parser ignora i caratteri dopo il primo token argomento.
- Il comando REM può apparire nell'output della fase 3, ma il comando non viene mai eseguito e il testo dell'argomento originale viene ripetuto - i caratteri di escape non vengono rimossi, tranne ...
- Se esiste un solo token argomento che termina con un senza escape
^
che termina la riga, il token argomento viene eliminato e la riga successiva viene analizzata e aggiunta al REM. Questo si ripete fino a quando non vi è più di un token o l'ultimo carattere non lo è ^
.
- Se il token di comando inizia con
:
, e questo è il primo round della fase 2 (non un riavvio a causa di CHIAMATA nella fase 6), allora
- Il token viene normalmente trattato come un'etichetta non eseguita .
- Il resto della linea viene analizzata, tuttavia
)
, <
, >
, &
e |
non hanno più significato speciale. L'intero resto della riga è considerato parte dell'etichetta "comando".
- La
^
continua ad essere speciale, il che significa che la linea di ripresa può essere utilizzato per modificare la linea successiva all'etichetta.
- Un'etichetta non eseguita all'interno di un blocco parentesi si tradurrà in un errore di sintassi irreversibile se non è immediatamente seguito da un comando o Eseguito etichetta sulla riga successiva.
(
non ha più un significato speciale per il primo comando che segue l' etichetta non eseguita .
- Il comando viene interrotto al termine dell'analisi dell'etichetta. Le fasi successive non hanno luogo per l'etichetta
- Esistono tre eccezioni che possono far sì che un'etichetta trovata nella fase 2 sia trattata come un'etichetta eseguita che continua ad analizzare attraverso la fase 7.
- C'è reindirizzamento che precede l'etichetta token, e v'è un
|
tubo o &
, &&
o ||
comando concatenazione sulla linea.
- C'è un reindirizzamento che precede il token dell'etichetta e il comando si trova all'interno di un blocco tra parentesi.
- Il token etichetta è il primo comando su una riga all'interno di un blocco tra parentesi e la riga sopra è terminata con un'etichetta non eseguita .
- Quanto segue si verifica quando viene rilevata un'etichetta eseguita nella fase 2
- L'etichetta, i suoi argomenti e il suo reindirizzamento sono tutti esclusi da qualsiasi output di eco nella fase 3
- Eventuali comandi concatenati successivi sulla riga vengono analizzati ed eseguiti completamente.
- Per ulteriori informazioni sulle etichette eseguite rispetto alle etichette non eseguite , vedere https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
Fase 3) Eco il / i comando / i analizzato / i Solo se il blocco comandi non è iniziato @
e ECHO era ON all'inizio del passaggio precedente.
Fase 4) %X
Espansione variabile FOR : solo se è attivo un comando FOR e vengono elaborati i comandi dopo DO.
- A questo punto, la fase 1 dell'elaborazione batch avrà già convertito una variabile FOR come
%%X
in %X
. La riga di comando ha regole di espansione percentuale diverse per la fase 1. Questo è il motivo utilizzato dalle righe di comando %X
ma i file batch utilizzano %%X
per le variabili FOR.
- I nomi delle variabili FOR fanno distinzione tra maiuscole e minuscole, ma
~modifiers
non fanno distinzione tra maiuscole e minuscole.
~modifiers
avere la precedenza sui nomi delle variabili. Se un carattere che segue ~
è sia un modificatore che un nome di variabile FOR valido ed esiste un carattere successivo che è un nome di variabile FOR attivo, il carattere viene interpretato come un modificatore.
- I nomi delle variabili FOR sono globali, ma solo nel contesto di una clausola DO. Se una routine viene CHIAMATA dall'interno di una clausola FOR DO, le variabili FOR non vengono espanse all'interno della routine CALLed. Ma se la routine ha il proprio comando FOR, allora tutte le variabili FOR attualmente definite sono accessibili ai comandi DO interni.
- I nomi delle variabili FOR possono essere riutilizzati nei FOR nidificati. Il valore FOR interno ha la precedenza, ma una volta chiuso INNER FOR, viene ripristinato il valore FOR esterno.
- Se ECHO era ON all'inizio di questa fase, la fase 3) viene ripetuta per mostrare i comandi DO analizzati dopo l'espansione delle variabili FOR.
---- Da questo punto in poi, ciascun comando identificato nella fase 2 viene elaborato separatamente.
---- Le fasi da 5 a 7 sono completate per un comando prima di passare al successivo.
Fase 5) Espansione ritardata: solo se l'espansione ritardata è attiva, il comando non si trova in un blocco tra parentesi su entrambi i lati di una pipe e il comando non è uno script batch "nudo" (nome dello script senza parentesi, CALL, concatenazione dei comandi, o pipe).
- Ogni token per un comando viene analizzato in modo indipendente per l'espansione ritardata.
- La maggior parte dei comandi analizza due o più token: il token di comando, il token degli argomenti e ogni token di destinazione del reindirizzamento.
- Il comando FOR analizza solo il token della clausola IN.
- Il comando IF analizza solo i valori di confronto, uno o due, a seconda dell'operatore di confronto.
- Per ogni token analizzato, controlla prima se ne contiene
!
. In caso contrario, il token non viene analizzato, importante per i ^
personaggi. Se il token contiene !
, scansiona ogni personaggio da sinistra a destra:
- Se si tratta di un carattere (
^
), il carattere successivo non ha alcun significato speciale, il carattere stesso viene rimosso
- Se si tratta di un punto esclamativo, cerca il punto esclamativo successivo (i punti di inserimento non vengono più osservati), espandi al valore della variabile.
- L'apertura consecutiva
!
viene compressa in una sola!
- Qualsiasi residuo non accoppiato
!
viene rimosso
- Espandere var a questo punto è "sicuro", perché i caratteri speciali non vengono più rilevati (nemmeno
<CR>
o <LF>
)
- Per una spiegazione più completa, leggi la seconda metà di questo dallo stesso thread di dbenham
- Fase punto esclamativo
Fase 5.3) Elaborazione del tubo: solo se i comandi sono su entrambi i lati di un tubo
Ogni lato del tubo viene elaborato in modo indipendente e asincrono.
- Se il comando è interno a cmd.exe, oppure si tratta di un file batch o se si tratta di un blocco comandi tra parentesi, viene eseguito in un nuovo thread cmd.exe tramite
%comspec% /S /D /c" commandBlock"
, quindi il blocco comandi ottiene un riavvio di fase, ma questa volta in modalità riga di comando.
- Se un blocco di comandi tra parentesi,
<LF>
vengono convertiti tutti con un comando prima e dopo <space>&
. Altri <LF>
sono spogliati.
- Questa è la fine dell'elaborazione per i comandi pipe.
- Vedi Perché l'espansione ritardata ha esito negativo quando si trova all'interno di un blocco di codice convogliato? per ulteriori informazioni sull'analisi e l'elaborazione delle pipe
Fase 5.5) Esegui reindirizzamento: ora viene eseguito qualsiasi reindirizzamento scoperto nella fase 2.
Fase 6) Elaborazione CHIAMATA / Raddoppio del cursore: solo se il token di comando è CHIAMATA o se il testo prima del primo delimitatore di token standard che si verifica è CHIAMATA. Se CALL viene analizzato da un token di comando più grande, la parte inutilizzata viene anteposta al token degli argomenti prima di procedere.
- Analizza il token argomenti per un non quotato
/?
. Se presente in qualsiasi punto all'interno dei token, interrompere la fase 6 e passare alla Fase 7, dove verrà stampato l'Help per CALL.
- Rimuovi il primo
CALL
, in modo che più CALL possano essere impilate
- Raddoppia tutti i punti di inserimento
- Riavviare le fasi 1, 1.5 e 2, ma non continuare con la fase 3
- Eventuali punti di raddoppio vengono ridotti a un punto di riferimento, purché non vengano quotati. Ma sfortunatamente, i trattini citati rimangono raddoppiati.
- La fase 1 cambia un po '
- Gli errori di espansione nel passaggio 1.2 o 1.3 interrompono la CHIAMATA, ma l'errore non è fatale - l'elaborazione batch continua.
- Le attività di fase 2 sono leggermente modificate
- Qualsiasi reindirizzamento non quotato, senza escape appena visualizzato che non è stato rilevato nel primo round della fase 2 viene rilevato, ma viene rimosso (incluso il nome del file) senza eseguire effettivamente il reindirizzamento
- Qualsiasi punto di inserimento non quotato, senza escape appena visualizzato alla fine della linea viene rimosso senza eseguire la continuazione della linea
- La CHIAMATA viene interrotta senza errori se viene rilevata una delle seguenti condizioni
- Appare di recente senza quotazione, senza escape
&
o|
- Il token di comando risultante inizia con non quotato, senza caratteri di escape
(
- Il primo token dopo l'inizio della CHIAMATA rimossa
@
- Se il comando risultante è un IF o FOR apparentemente valido, l'esecuzione fallirà successivamente con un errore che indica che
IF
oFOR
non viene riconosciuto come comando interno o esterno.
- Ovviamente la CHIAMATA non viene interrotta in questo secondo round della fase 2 se il token di comando risultante è un'etichetta che inizia con
:
.
- Se il risultante token di comando è CALL, riavvia la Fase 6 (si ripete fino a quando non viene più eseguita la CHIAMATA)
- Se il risultante token di comando è uno script batch o un'etichetta: quindi l'esecuzione della CHIAMATA è completamente gestita dal resto della Fase 6.
- Inserire l'attuale posizione del file di script batch nello stack di chiamate in modo che l'esecuzione possa riprendere dalla posizione corretta al termine della CHIAMATA.
- Imposta i token argomento% 0,% 1,% 2, ...% N e% * per la CHIAMATA, usando tutti i token risultanti
- Se il token di comando è un'etichetta che inizia con
:
, allora
- Riavvia fase 5. Ciò può influire su cosa: l'etichetta è CHIAMATA. Ma poiché i token% 0 ecc. Sono già stati impostati, non modificherà gli argomenti passati alla routine CALLed.
- Eseguire l'etichetta GOTO per posizionare il puntatore del file all'inizio della subroutine (ignorare tutti gli altri token che possono seguire l'etichetta:) Vedere la Fase 7 per le regole su come funziona GOTO.
- Se manca il token dell'etichetta: o l'etichetta: non viene trovata, lo stack di chiamate viene immediatamente estratto per ripristinare la posizione del file salvato e CALL viene interrotto.
- Se l'etichetta: contiene /?, Viene stampata la guida di GOTO invece di cercare l'etichetta:. Il puntatore al file non si sposta, in modo tale che il codice dopo la CHIAMATA venga eseguito due volte, una volta nel contesto della CHIAMATA, e poi di nuovo dopo il ritorno della CHIAMATA. Vedi Perché CALL stampa il messaggio di aiuto GOTO in questo script e perché i comandi dopo vengono eseguiti due volte? per maggiori informazioni.
- Altrimenti controllo del trasferimento allo script batch specificato.
- Esecuzione di CALLed: l'etichetta o lo script continua fino a raggiungere EXIT / B o la fine del file, a quel punto lo stack CALL viene espulso e l'esecuzione riprende dalla posizione del file salvato.
La fase 7 non viene eseguita per gli script CHIAMATI o: etichette.
- Altrimenti il risultato della fase 6 passa alla fase 7 per l'esecuzione.
Fase 7) Esegui: il comando viene eseguito
- 7.1 - Esegui comando interno - Se il token di comando è citato, salta questo passaggio. Altrimenti, tenta di analizzare un comando interno ed eseguire.
- Vengono eseguiti i seguenti test per determinare se un token di comando non quotato rappresenta un comando interno:
- Se il token di comando corrisponde esattamente a un comando interno, quindi eseguirlo.
- In caso contrario, interrompere il token di comando prima della prima occorrenza di
+
/
[
]
<space>
<tab>
,
;
o =
Se il testo precedente è un comando interno, ricordare quel comando
- Se in modalità riga di comando o se il comando proviene da un blocco tra parentesi, blocco di comando SE vero o falso, blocco di comando FOR DO o coinvolto nella concatenazione dei comandi, eseguire il comando interno
- Altrimenti (deve essere un comando autonomo in modalità batch) scansiona la cartella corrente e il PERCORSO alla ricerca di un file .COM, .EXE, .BAT o .CMD il cui nome di base corrisponde al token di comando originale
- Se il primo file corrispondente è un .BAT o .CMD, vai a 7.3.exec ed esegui quello script
- Altrimenti (la corrispondenza non trovata o la prima corrispondenza è .EXE o .COM) esegue il comando interno ricordato
- Altrimenti rompi il token di comando prima della prima occorrenza di
.
\
o :
Se il testo precedente non è un comando interno, vai a 7.2 Il
testo precedente potrebbe essere un comando interno. Ricorda questo comando.
- Interrompi il token di comando prima della prima occorrenza di
+
/
[
]
<space>
<tab>
,
;
o =
Se il testo precedente è un percorso di un file esistente, vai a 7.2
Else esegui il comando interno ricordato.
- Se un comando interno viene analizzato da un token di comando più grande, la parte inutilizzata del token di comando viene inclusa nell'elenco degli argomenti
- Solo perché un token di comando viene analizzato come comando interno non significa che verrà eseguito correttamente. Ogni comando interno ha le sue regole su come vengono analizzati gli argomenti e le opzioni e su quale sintassi è consentita.
- Tutti i comandi interni stamperanno la guida invece di eseguire la loro funzione se
/?
rilevati. La maggior parte riconosce /?
se appare ovunque negli argomenti. Ma alcuni comandi come ECHO e SET stampano aiuto solo se inizia il primo token argomento /?
.
- SET ha alcune semantiche interessanti:
- Se un comando SET ha una virgoletta prima che il nome della variabile e le estensioni siano abilitate
set "name=content" ignored
-> valore = content
allora il testo tra il primo segno di uguale e l'ultima citazione viene utilizzato come contenuto (escluso il primo uguale e l'ultima citazione). Il testo dopo l'ultima citazione viene ignorato. Se dopo il segno di uguale non è presente alcuna citazione, il resto della riga viene utilizzato come contenuto.
- Se un comando SET non ha una virgoletta prima del nome
set name="content" not ignored
-> valore = "content" not ignored
allora l'intero resto della riga dopo la parità è usato come contenuto, incluse tutte le virgolette eventualmente presenti.
- Viene valutato un confronto IF e, a seconda che la condizione sia vera o falsa, viene elaborato il blocco di comando dipendente già analizzato appropriato, a partire dalla fase 5.
- La clausola IN di un comando FOR viene ripetuta in modo appropriato.
- Se questo è un FOR / F che scorre l'output di un blocco comandi, allora:
- La clausola IN viene eseguita in un nuovo processo cmd.exe tramite CMD / C.
- Il blocco comandi deve passare l'intero processo di analisi una seconda volta, ma questa volta in un contesto da riga di comando
- ECHO si avvia su ON e l'espansione ritardata di solito inizia disabilitata (a seconda delle impostazioni del registro)
- Tutte le modifiche all'ambiente apportate dal blocco comandi della clausola IN andranno perse al termine del processo cmd.exe figlio
- Per ogni iterazione:
- I valori delle variabili FOR sono definiti
- Il blocco di comandi DO già analizzato viene quindi elaborato, a partire dalla fase 4.
- GOTO utilizza la seguente logica per individuare: label
- L'etichetta viene analizzata dal token del primo argomento
- Lo script viene scansionato per la prossima occorrenza dell'etichetta
- La scansione inizia dalla posizione corrente del file
- Se viene raggiunta la fine del file, la scansione torna all'inizio del file e continua fino al punto di partenza originale.
- La scansione si interrompe alla prima occorrenza dell'etichetta rilevata e il puntatore del file viene impostato sulla riga immediatamente successiva all'etichetta. L'esecuzione della sceneggiatura riprende da quel punto. Si noti che un GOTO vero di successo interromperà immediatamente qualsiasi blocco di codice analizzato, inclusi i cicli FOR.
- Se l'etichetta non viene trovata o il token dell'etichetta è mancante, GOTO ha esito negativo, viene stampato un messaggio di errore e lo stack di chiamate viene visualizzato. Funziona in modo efficace come EXIT / B, ad eccezione dei comandi già analizzati nel blocco di comandi corrente che seguono GOTO vengono comunque eseguiti, ma nel contesto del CALLer (il contesto esistente dopo EXIT / B)
- Consulta https://www.dostips.com/forum/viewtopic.php?f=3&t=3803 per una descrizione più precisa delle regole utilizzate per l'analisi delle etichette.
- RENAME e COPY accettano entrambi i caratteri jolly per i percorsi di origine e destinazione. Ma Microsoft fa un lavoro terribile documentando come funzionano i caratteri jolly, specialmente per il percorso target. Un utile set di regole per i caratteri jolly è disponibile in Come il comando Windows RENAME interpreta i caratteri jolly?
- 7.2 - Eseguire la modifica del volume - Altrimenti se il token di comando non inizia con una virgoletta, è lungo esattamente due caratteri e il 2o carattere è due punti, quindi modificare il volume
- Tutti i token argomento vengono ignorati
- Se non è possibile trovare il volume specificato dal primo carattere, interrompere con un errore
- Un token di comando
::
comporterà sempre un errore a meno che SUBST non venga utilizzato per definire un volume per ::
Se SUBST viene utilizzato per definire un volume per ::
, il volume verrà modificato, non verrà trattato come un'etichetta.
- 7.3 - Esegui comando esterno - Altrimenti prova a trattare il comando come comando esterno.
- Se in modalità riga di comando e il comando non è citato e non inizia con una specifica volume, bianco-spazio,
,
, ;
, =
o +
poi rompere il comando gettone alla prima occorrenza di <space>
,
;
o =
e anteporre il resto all'argomento gettone (s).
- Se il 2o carattere del token di comando è due punti, verificare che sia possibile trovare il volume specificato dal 1o carattere.
Se non è possibile trovare il volume, interrompere con un errore.
- Se in modalità batch e il token di comando inizia con
:
, quindi vai a 7.4
Nota che se il token etichetta inizia con ::
, questo non verrà raggiunto perché il passaggio precedente sarà interrotto con un errore a meno che SUBST non sia usato per definire un volume per ::
.
- Identificare il comando esterno da eseguire.
- Questo è un processo complesso che può coinvolgere il volume corrente, la directory corrente, la variabile PATH, la variabile PATHEXT e le associazioni di file.
- Se non è possibile identificare un comando esterno valido, interrompere con un errore.
- Se in modalità riga di comando e il token di comando inizia con
:
, quindi vai a 7.4
Nota che questo viene raggiunto raramente perché il passaggio precedente sarà interrotto con un errore a meno che il token di comando non inizi con ::
e SUBST viene utilizzato per definire un volume per ::
, e il l'intero token di comando è un percorso valido per un comando esterno.
- 7.3.exec - Esegue il comando esterno.
- 7.4 - Ignora un'etichetta - Ignora il comando e tutti i suoi argomenti se il token di comando inizia con
:
.
Le regole in 7.2 e 7.3 possono impedire a un'etichetta di raggiungere questo punto.
Parser della riga di comando:
Funziona come BatchLine-Parser, tranne:
Fase 1) Espansione percentuale:
- No
%*
, %1
ecc. Argomento di espansione
- Se var non è definito,
%var%
rimane invariato.
- Nessuna gestione speciale di
%%
. Se var = content, si %%var%%
espande in %content%
.
Fase 3) Eco i comandi analizzati
- Questo non viene eseguito dopo la fase 2. Viene eseguito solo dopo la fase 4 per il blocco comandi FOR DO.
Fase 5) Espansione ritardata: solo se DelayedExpansion è abilitato
- Se var non è definito,
!var!
rimane invariato.
Fase 7) Esegui comando
- Tentativi di CHIAMARE o GOTO a: etichetta genera un errore.
- Come già documentato nella fase 7, un'etichetta eseguita può provocare un errore in diversi scenari.
- Le etichette eseguite in batch possono causare un errore solo se iniziano con
::
- Le etichette eseguite dalla riga di comando generano quasi sempre un errore
Analisi di valori interi
Esistono molti contesti diversi in cui cmd.exe analizza i valori interi dalle stringhe e le regole sono incoerenti:
SET /A
IF
%var:~n,m%
(espansione della sottostringa variabile)
FOR /F "TOKENS=n"
FOR /F "SKIP=n"
FOR /L %%A in (n1 n2 n3)
EXIT [/B] n
I dettagli per queste regole sono disponibili in Regole su come CMD.EXE analizza i numeri
Per chiunque desideri migliorare le regole di analisi di cmd.exe, nel forum DosTips è presente un argomento di discussione in cui è possibile segnalare problemi e fornire suggerimenti.
Spero che aiuti
Jan Erik (jeb) - Autore originale e scopritore delle fasi
Dave Benham (dbenham) - Molto contenuto aggiuntivo e editing