Che cosa significa trattino nel file batch di Windows?


1

In particolare, ho problemi a comprendere i trattini nelle righe seguenti, che provengono dai wikibook

if not -%1-==-- echo Argument one provided
if -%1-==-- echo Argument one not provided & exit /b

Per verificare se esiste o definisce una variabile, ci sono sostanzialmente due modi, che ho imparato da qui :

IF DEFINED MyVar (ECHO MyVar IS defined) ELSE (ECHO MyVar is NOT defined)

IF "%MyVar%"=="" (ECHO MyVar is NOT defined) ELSE (ECHO MyVar IS defined)

Quindi, cosa significano (1) i trattini attorno all'argomento% 1 e (2) i trattini dopo il segno ==?


1
un tuo commento menzionato %%, che viene utilizzato in un ciclo for in un file batch come %% f non per i parametri della riga di comando batch% 1% 2% 3. Dalla riga di comando puoi fare for %1 in (*.*) do @echo %1e sarebbe ambiguo farlo in un file batch, quindi per le istruzioni quando all'interno di un file batch usano %% ma i parametri batch (che tra l'altro sono sempre e solo in un file batch), sono sempre% 1 ,% 2 ecc.
barlop

Caro midnite: è il 2015. Perché usi ancora un linguaggio di programmazione così scadente come lo script batch? È possibile passare a VBScript, JScript, PowerShell o una delle tante altre opzioni .
indimenticabile il

"Tuttavia, questi richiedono che l'interprete del linguaggio di scripting sia installato prima di poter essere utilizzato" - nessun danno per saperne di più, esp funziona in modo nativo sulla maggior parte dei PC ;-)
midnite

1
@midnite Immagino che con batch, c'è un limite al numero di problemi che puoi incontrare ... Quindi ho imparato negli anni chiedendo e giocherellando .. E sembrano esserci geni che hanno capito cose che non sono scritte in nessun riferimento, quando diventa davvero difficile. Ad esempio .. dave Benham e Jeb .. Penso sia post qui, sia sul forum Dostips .. E come riferimento c'è l'originale vfrazee.com/ms-dos/6.22/help che è apparso in DOS quando hai eseguito HELP.COM (puoi fare clic ad es. SE poi esempi), e c'è ss64.com/nt
barlop

1
questi piccoli programmi in C possono aiutare a mostrare come i programmi suddividono le cose in parametri per aiutare a risolvere i problemi con le citazioni di escapign superuser.com/questions/944745/sed-command-with-apostrophe/… E se sei mai andato pazzo, allora jeb e dbenham hanno scritto post su come funziona l'interprete lotto .. trovati tramite test, piuttosto che qualsiasi riferimento stackoverflow.com/questions/4094699/...
barlop

Risposte:


6

Considera questo

C:\>if not -%1-==-- echo Argument one provided
Argument one provided

C:\>if not P%1P==PP echo Argument one provided
Argument one provided

Dovrebbe essere evidente che il carattere meno / trattino viene semplicemente utilizzato per facilitare la designazione di un valore vuoto. Quel simbolo specifico non ha un significato speciale in quell'espressione: è trattato come qualsiasi altro carattere non speciale.

Possiamo aggiungere spazi per rendere più chiaro che l' ==operatore non viene modificato dai caratteri circostanti

C:\>if not P%1P == PP echo Argument one provided
Argument one provided

In generale, è meglio usare approcci convenzionali che più persone capiranno immediatamente (ad es. L'uso di virgolette).

C:\>if not "%1"=="" echo Argument one provided
Argument one provided

Con DOS e forse le prime versioni di Windows, credo che ci siano stati alcuni problemi (che non ricordo) con l'uso delle virgolette che hanno portato le persone a usare i caratteri stampabili in questo modo. Non ho provato il caso in cui% 1 contiene ad esempio un segno di virgolette.


Vedo. Grazie mille. Quindi significa essenzialmente concatenare due caratteri prima e dopo la variabile, non è vero? OTOH, ho provato a usare la definedparola chiave per verificare se il parametro esiste. Entrambi IF DEFINED %1e IF DEFINED %%1sembrano non funzionare. Mi daresti qualche suggerimento?
mezzogiorno

Scrivi "il carattere meno / trattino viene semplicemente utilizzato per semplificare la designazione di un valore vuoto" <--- la parola "semplificare" non è probabilmente una buona parola da usare perché non semplifica ( qualunque cosa significherebbe semplificare). Ma come sai, impedisce un errore per quando non viene fornito alcun argomento.
barlop

@barlop: grazie per il commento. Risposta modificata.
RedGrittyBrick il

Buona modifica, ma alla fine hai scritto "Con DOS e forse le prime versioni di Windows, credo che ci siano stati alcuni problemi (che non ricordo) con l'uso delle virgolette" <- Lo sono ancora. usando "% 1" vedi la mia risposta .. Inizialmente ho detto che le virgolette erano ottime intorno a un% 1, quindi supercat, ho commentato e l'ho corretto.
barlop

Scrivi "non ho provato il caso in cui% 1 contiene ad esempio un segno di virgolette". <- Se l'utente li fornisce e tu non fai "% 1", allora va bene. Se l'utente li fornisce e li aggiungi con "% 1", allora non va bene
barlop

4

È importante quando si utilizza% 1 per mettere qualcosa attorno ad esso per evitare che il file batch si rompa quando% 1 è vuoto, perché% 1 non è una variabile che viene sostituita con il valore, come SQL injection un esempio di iniezione in batch , e quando il valore è nulla e% 1 è in un IF, viene visualizzato un codice non funzionante. if %1==""diventa if == ""e dà un errore.

Per quanto riguarda il motivo per cui se definito non funziona su% 1,% 1 è il valore non la variabile, quindi definito non funziona lì. Per il codice che funziona con% 1 vuoto, è necessario un codice che non si interrompa quando% 1 viene sostituito con nulla. Prova if "%1"=="" o provaif [%1]==[]

Per dire -% 1 sembra un po 'confuso, non mi sembra una buona convenzione! Tecnicamente potresti persino fare if a%1==a%1 o if %1a==%1ama la convenzione tende ad essere[]

Puoi usare le virgolette, oppure [] o qualsiasi altro carattere. Ma come ha sottolineato il supercat nel commento, le virgolette non sono una buona idea intorno a% 1. (Perché se% 1 contiene spazi, l'utente include le virgolette in ciò che viene passato a% 1 e se c'è uno spazio in% 1 e nel file batch si inseriscono virgolette attorno a% 1, le virgolette verranno annullate e lo spazio non quotato causerà un errore).

Se stavi facendo un IF sulla riga di comando e non testassi alcuna variabile, non avresti% 1 e non avresti nemmeno bisogno di []. Diresti IF "a b c"=="a b c" echo a o IF a==b echo a Se in un file batch hai spesso% 1 e invece di usare le virgolette attorno a% 1, usa ad esempio uno o due caratteri attorno ad esempio [%1]e usa le virgolette se devi conservare spazi e non è un% 1 egeg IF [%1]==[a]o IF [%1]==["a b"] echo aDon't do "%1"perché% 1 potrebbe già avere delle virgolette che le tue virgolette annulleranno e quindi se% 1 ha uno spazio, l'istruzione if si interrompe.

Se eri sulla riga di comando e stavi testando una variabile, dipende se la variabile ha virgolette. Puoi vedere i contenuti.

È possibile che una variabile abbia uno spazio e non contenga virgolette.

Quindi, in questo caso particolare della riga di comando, mettere le virgolette attorno a% a% non raddoppierà le virgolette e devi mettere le virgolette attorno a% a% se vuoi testarlo contro "a b"

C:\>set a=a b

C:\>echo %a%
a b

C:\>IF %a%=="a b" echo sdf
b=="a b" was unexpected at this time.

C:\>IF "%a%"=="a b" echo sdf
sdf

So ^^^ we want "%a%"

Considerando che se% a% contenesse virgolette, sarebbe un caso diverso

C:\>set a="a b"

C:\>echo %a%
"a b"

C:\>IF %a%=="a b" echo a
a

C:\>IF "%a%"=="a b" echo a
b""=="a b" was unexpected at this time.

C:\>

^^^^ So there we want %a% without quotes around it.

Quindi è tutta una questione se la variabile o il parametro contiene virgolette. Se% 1 contiene spazi, conterrà virgolette. Quindi sappiamo che se confrontassimo% 1 con "a b", allora w non farebbe "% 1". E se% 1 non contenesse virgolette non conterrebbe spazi, quindi non faremmo "% 1" Quindi penso che non vorrai mai fare "% 1". Quindi, se% 1 contiene spazi, ci saranno virgolette all'interno di% 1 e gli spazi saranno già conservati.

Ho cancellato il seguito alla luce del commento di Supercat. E ho aggiunto altro al mio post sopra.

Le virgolette sono migliori intorno a% 1, piuttosto che [] o ad alcuni caratteri come A o -, perché ad esempio, se usi [], non manterrà gli spazi

C: \> if [dab] == [dab] echo sdf

a era inaspettato in questo momento.

Di ' if "d a b"che funzionerà. Quindi if "%1"è meglio di altri personaggi come if [%1]o a%1ao-%1


2
L'unico modo %1per espandersi in qualcosa che contiene spazi sarà se l'argomento contiene virgolette. In tal caso, circondarsi %1di virgolette produrrà un comportamento non funzionante e circondarlo con qualcos'altro dovrebbe funzionare.
supercat

2
Cosa succede se l'argomento citato contiene spazi?
supercat

1
@supercat ah, vedo, ben individuato. if "" 2""==""2"" echo anon riesce. E nel caso in cui nessuno lo sappia .. ""Avrà l'effetto di attivare e disattivare la quotazione.
barlop

1
@midnite ha una certa somiglianza con la concatenazione che vedi in linguaggi più avanzati, ma penso che funzionalmente non tanto 'cos con java ecc., la concatenazione è di due entità separate anche quando fai "asdf" + "asdf". Considerando che con cmd, "asdf""asdf"non unisce due oggetti separati. Il primo "significa attivare una modalità in cui vengono conservati gli spazi e alcuni altri caratteri. Il successivo" significa disattivare quella modalità. Il prossimo lo accende. Quindi puoi dire "asdf asdf" o puoi dire asdf" "asdf Quindi 2""non dovrebbe sembrare troppo complicato. (ma a volte capire come funziona cmd / batch è complicato)
barlop

1
@midnite dubito anche che il file batch (in generale) distingua stringhe e numeri, sebbene alcuni comandi o funzionalità all'interno del comando lo facciano. Se 2 è un numero o una stringa dipende dall'interpretazione. Se dici che echo 2non c'è conversione di 2 in una stringa. Suppongo che tecnicamente con i computer sia tutto codificato (non dirò personaggi) squiggles / glifi. Alcuni possono guardare la presentazione, se virgolette o meno, e quindi trattarla di conseguenza, come un numero (per il calcolo) o come una stringa (per ordinarli in ordine alfabetico). O proprio come i glifi codificati sono numeri o stringhe.
barlop

1

Non sono sicuro di averlo capito, quindi fammi vedere se riesco a semplificarlo.

Supponiamo che il tuo file batch riceva un valore %1dalla riga di comando e che tu voglia vedere se è "gatto" o "cane". Puoi provarlo:

if %1 == cat goto CAT
if %1 == dog goto DOG
REM Default: Complain about no dog or cat
goto OOPS
:CAT
echo I'm a cat!
REM Successful, so skip to end
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo I didn't see a cat or dog!
REM This just falls through to the end
:END

%1 viene sostituito con il testo di gatto o cane (diciamo cane), quindi l'interprete vede effettivamente questo:

if dog == cat goto CAT
if dog == dog goto DOG

Ma se la persona che esegue lo script non includeva un valore nella riga di comando, l'interprete vedrà questo:

if  == cat goto CAT
if  == dog goto DOG

Questa è una sintassi errata e genererà un errore. Quindi la convenzione è di includere 1 o più caratteri e testare prima nessuna variabile, qualcosa del genere:

if %1* == * goto OOPS
REM If no value passed in, this is seen as  if * == *  which evaluates to true
if %1 == cat goto CAT
if %1 == dog goto DOG
goto END
:CAT
echo I'm a cat!
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo You were supposed to include a type of pet!
:END

Se non %1valuta nulla, i caratteri extra sono ancora lì per mantenere la sintassi corretta. Io uso *, ma le virgolette o le esclamazioni sono anche comuni, come "%1"o %1!, così come trattini, come --%1o -%1-, ecc.

Amico, non posso credere di ricordare ancora tutto questo. :-) Spero che questo possa essere d'aiuto!


Hai scritto "Ma se la persona che esegue lo script non includesse una variabile", potresti voler dire "un valore" perché è più un valore che una variabile. Passa i dati, forse si potrebbe dire un valore. E per quanto riguarda il modo in cui viene passato, (nella programmazione di alcuni linguaggi più avanzati, puoi avere "passa per valore" o "passa per riferimento" immagino che si direbbe che questo è passato per iniezione!
barlop

"potresti voler dire 'un valore [anziché una variabile]" ... Oops! Hai ragione!
furry_marmot
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.