Não obtendo a saída esperada ao ecoar

0

Eu escrevi o seguinte script em lote para fazer o eco do caminho de uma pasta.

set TW_prod_cer_path=D:\prod_path 
set /p client="Enter client: " 

    if %client% equ TW (  
        setlocal enabledelayedexpansion
        set prod_path=!client!_prod_cer_path
        echo !prod_path!
        echo %!prod_path!%
    )

E estou recebendo a saída abaixo

Enter client: TW
TW_prod_cer_path
ECHO is off.

Mas minha saída esperada é:

Enter client: TW
TW_prod_cer_path
D:\prod_path

Alguém poderia explicar o motivo disso e também a ação corretiva a ser tomada para obter o resultado esperado?

    
por Mathew 06.02.2017 / 06:58

2 respostas

0

O primeiro problema aqui é que a expansão non -delayed - o %…% - é feita para toda a instrução if , incluindo todo o bloco entre colchetes. (É um truque parser; cmd ainda considera a coisa toda uma única linha de comando.)

Em outras palavras, %…% expansões acontecem antes do comando set , apesar de estar acima.

O segundo problema é que a ordem de expansão atrasada / não atrasada está errada. Se você quiser "excluir a referência" de uma variável, precisará que o nome dela seja expandido não mais tarde, mas anterior; , por exemplo,

set foo=value
set bar=foo
echo !%bar%!

Já considerou outra linguagem de programação, como o PowerShell? Tem hashtables:

$prod_paths = @{
    "TW" = "D:\prod_path";
}
$client = Read-Host -Prompt "Enter client"
if ($client -ceq "TW") {
    echo $prod_paths.Item($client)
}
    
por 06.02.2017 / 07:45
0

Quando o comando if é analisado, o analisador vê

echo %!prod_path!%

e aqui há um problema: a expansão normal ( %var% ) é executada antes da expansão atrasada ( !var! ), então este código tenta recuperar o conteúdo de uma variável quando o nome da variável ainda não está definido. / p>

É claro que a sintaxe inversa também não funcionará

echo !%prod_path%!

Nesse caso, o nome da variável é avaliado no tempo de análise, mas na hora da análise a variável ainda não tem valor, portanto, quando ocorrer uma expansão atrasada, não haverá um nome de variável para leitura.

Você precisa de uma expansão com atraso duplo, ou seja, você precisa de algo como

echo !!prod_path!!

Mas esta não é uma sintaxe válida.

Portanto, precisamos usar a expansão atrasada para recuperar o nome da variável que precisamos ler e, em seguida, atrasar a expansão para recuperar o valor dentro da variável.

A solução mais simples é alterar a estrutura do código para evitar o problema ( call uma subrotina, use goto , ...), mas existe outra alternativa.

for %%a in (!prod_path!) do echo !%%a!

Recupere o nome da variável (primeira expansão atrasada), armazene o valor recuperado dentro de um parâmetro for substituível e, em seguida, leia o valor na variável que está sendo referenciada pelo parâmetro substituível (segunda expansão atrasada)

    
por 09.02.2017 / 11:26