O que significa hífen no arquivo de lote do Windows?

1
Em particular, tenho problemas em entender os hífens nas seguintes linhas, que são de wikibooks

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

Para testar se uma variável existe ou está definida, há basicamente duas maneiras, que aprendi com aqui :

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)

Então, o que significa (1) os hífens ao redor do argumento% 1 e (2) os hifens após o sinal == significar?

    
por midnite 31.07.2015 / 11:52

3 respostas

6

Considere isso

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

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

Deve ficar evidente que o caractere menos / hífen está sendo usado simplesmente para facilitar a designação de um valor vazio. Esse símbolo específico não tem nenhum significado especial nessa expressão - ele é tratado como qualquer outro caractere não especial.

Podemos adicionar espaços para deixar mais claro que o operador == está não sendo modificado pelos caracteres adjacentes

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

Geralmente, é melhor usar abordagens convencionais que mais pessoas entendam mais imediatamente (por exemplo, uso de marcas de cotação).

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

Com o DOS e talvez versões anteriores do Windows, acredito que houve alguns problemas (que não me lembro) em usar aspas, o que levou as pessoas a usarem caracteres imprimíveis dessa maneira. Eu não tentei o caso em que% 1 contém uma marca de aspas, por exemplo.

    
por 31.07.2015 / 12:04
4

É importante usar% 1 para colocar algo em torno dele para evitar que o arquivo em lote seja quebrado quando% 1 estiver vazio, porque% 1 não é uma variável que é substituída pelo valor, como injeção de SQL um exemplo de injeção em lote e quando o valor é nada e o% 1 está em um IF, então você tem código quebrado. if %1=="" torna-se if == "" e apresenta um erro.

Por que, se definido não funciona em% 1,% 1 é o valor não a variável, portanto, portanto, definido não funciona lá. Para o código que funciona para% 1 estar vazio, você precisa de um código que não seja quebrado quando% 1 for substituído por nada. Experimente if "%1"=="" ou tente if [%1]==[]

Dizer -% 1 parece um pouco confuso, não parece uma boa convenção para mim! Tecnicamente, você poderia até mesmo fazer if a%1==a%1 ou if %1a==%1a , mas a convenção tende a ser []

Você pode usar aspas, ou [] ou qualquer caractere (s). Mas como supercat apontou no comentário, as citações não são uma boa ideia em torno de um% 1. (Porque se o% 1 contiver espaços, o usuário incluirá aspas no que é passado para% 1, e se houver um espaço no% 1 e no arquivo em lote você colocar aspas ao redor do% 1, as cotações serão canceladas e o espaço não mencionado causará um erro).

Se você estivesse fazendo um IF na linha de comando e não testando nenhuma variável, você não teria% 1 e nem precisaria []. Você diria IF "a b c"=="a b c" echo a ou IF a==b echo a Se estiver em um arquivo de lote, geralmente você tem% 1 e, em vez de usar aspas em torno de% 1, use, por exemplo, um ou dois caracteres em torno dele, por ex. [%1] e use aspas se você precisar preservar espaços e não for% 1, por exemplo, por exemplo. IF [%1]==[a] ou IF [%1]==["a b"] echo a Não faça "%1" porque o% 1 já pode ter aspas que serão canceladas e, se o% 1 tiver um espaço, sua declaração if será quebrada.

Se você estava na linha de comando e estava testando uma variável, isso depende de a variável ter aspas. Você pode olhar o conteúdo.

É possível que uma variável tenha um espaço e não contenha aspas.

Portanto, neste caso de linha de comando específico, colocar aspas em torno de% a% não irá aspas duplas, e você terá que colocar aspas em torno do% a% se quiser testá-lo com "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 que, se% a% continha citações, seria um caso diferente

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.

Portanto, é uma questão de saber se a variável ou parâmetro contém aspas. Se o% 1 tiver espaços, ele conterá aspas. Então, sabemos que, se comparássemos% 1 a "a b", então não faríamos "% 1". E se% 1 não continha aspas, não conteria espaços, por isso, não faríamos "% 1". Então, acho que você nunca faria "% 1". Portanto, se% 1 contiver espaços, haverá citações dentro de% 1 e os espaços já serão preservados.

Eu riscou o abaixo à luz do comentário do supercat. E adicionei mais ao meu post acima.

As citações são melhores em torno do% 1, em vez de [] ou de algum caractere como A ou -, porque, por exemplo, se você usar [], ele não preservará espaços

C: \ > if [d a b] == [d a b] echo sdf

a foi inesperado neste momento.

Diga if "d a b" que funcionará. Então if "%1" é melhor que outros caractere (s) como if [%1] ou a%1a ou -%1

    
por 31.07.2015 / 14:08
1

Não tenho certeza se você está conseguindo, então deixe-me ver se posso simplificar isso.

Digamos que seu arquivo de lote receba um valor %1 na linha de comando e você queira ver se é "cat" ou "dog". Você pode testar isso:

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 é substituído pelo texto de gato ou cachorro (digamos, cachorro), então o intérprete realmente vê isso:

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

Mas se a pessoa que está executando o script não incluir um valor na linha de comando, o intérprete verá isto:

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

Isso é uma sintaxe incorreta e gerará um erro. Portanto, a convenção é incluir 1 ou mais caracteres e testar primeiro a variável, algo assim:

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 %1 não avaliar nada, os caracteres extras ainda estarão lá para manter a sintaxe correta. Eu uso * , mas citações ou exclamações também são comuns, como "%1" ou %1! , assim como hífens, como --%1 ou -%1- , etc.

Cara, eu não posso acreditar que ainda me lembro de tudo isso. :-) Espero que isso ajude!

    
por 31.07.2015 / 19:23