Lote: Como corrigir o comportamento incorreto de sobrescrita variável ao analisar a saída

Em um arquivo de lote, estou verificando as informações do Baseboard, com o seguinte:
BaseboardCheck.cmd

@echo off setlocal enabledelayedexpansion for /f "tokens=1,2* delims==" %%a in ('wmic baseboard get /format:list') DO ( if ["%%a"] EQU ["Product"] ( set PlatformInfo=%%b if defined PlatformInfo ( echo.!PlatformInfo! echo.!PlatformInfo!This overwrites the variable ) ) if ["%%a"] EQU ["Version"] ( set BaseboardVersion=%%b if defined BaseboardVersion ( echo.!BaseboardVersion! echo.!BaseboardVersion!This overwrites the variable ) ) ) 

O problema acima: As variables ​​são sobrescritas, em vez de anexadas, quando são excluídas.
Saída:

 DX79SI This overwrites the variable AAG28808-600 This overwrites the variable 

O que eu gostaria de encontrar é:

 DX79SI DX79SIThis overwrites the variable AAG28808-600 AAG28808-600This overwrites the variable 

Passei algumas horas nisto (e continuarei a fazê-lo), mas espero que alguém tenha se deparado com esse problema. E estou esperando que qualquer outra pessoa que tenha esse problema de análise possa evitá-lo no futuro.

O problema adicional que surge disso é que parece quebrar a lógica condicional.

Atualizar
Depois de toda a assistência, eu encontrei esta solução:

 for /f "skip=2 tokens=1,2 delims=," %%a in ('wmic baseboard get Product^,Version^,Width /format:csv') do ( set Platform=%%a set BaseboardVersion=%%b ) echo.Platform: %Platform% echo.Version %BaseboardVersion%. 

Sim, você tem um problema, mas não é o que você pensa.

wmic tem um comportamento específico: no final de cada saída de linha há um retorno de carro adicional, ou seja, cada linha termina com 0x0d 0x0d 0x0a

Esse retorno de carro adicional é armazenado dentro de sua variável e, quando é ecoado no console, você obtém os dados e o retorno de carro, portanto, se a variável for seguida por mais texto, pois o cursor foi posicionado no início da linha retorno de carro), este texto é ecoado nos dados ecoados anteriores.

Como resolver?

 @echo off setlocal enabledelayedexpansion for /f "tokens=1,* delims==" %%a in ('wmic baseboard get /format:list') DO ( if ["%%a"] EQU ["Product"] ( for /f "delims=" %%c in ("%%b") do set "PlatformInfo=%%c" if defined PlatformInfo ( echo(!PlatformInfo! echo(!PlatformInfo!This does not overwrite the variable ) ) if ["%%a"] EQU ["Version"] ( for /f "delims=" %%c in ("%%b") do set "BaseboardVersion=%%c" if defined BaseboardVersion ( echo(!BaseboardVersion! echo(!BaseboardVersion!This does not overwrite the variable ) ) ) 

Nesse caso, sem alterar sua lógica de código, um adicional for /f comando for /f pode ser usado para remover o retorno de carro adicional

Uau, foi muito difícil descobrir o que está acontecendo aqui.

Primeiro, não pude acreditar no que acontece na execução de arquivos em lote.

Depois de muitas tentativas eu executei no Windows XP SP3 x86

 wmic.exe baseboard get /format:list > Output.txt 

e olhou no arquivo Output.txt com visualizador do gerenciador de arquivos Total Commander. Eu vi duas linhas vazias no topo, mas isso realmente não importa. Então continuei com outras tentativas.

Mais tarde eu abri Output.txt no editor de texto UltraEdit e vi imediatamente na barra de status U-DOS, indicando que o arquivo de saída está codificado em UTF-16 little endian tendo terminadores de linha DOS. Eu mudei para o modo de edição hexadecimal e pude ver

 00000000h: FF FE 0D 00 0A 00 0D 00 0A 00 43 00 61 00 70 00 ; ÿþ........Cap 00000010h: 74 00 69 00 6F 00 6E 00 3D 00 ; tion=. 

Portanto, o arquivo de saída é de fato um arquivo Unicode com UTF-16 LE BOM. Não há CR CR LF. Todas as terminações de linha estão corretas no par CR LF (retorno de carro + alimentação de linha).

Agora eu pesquisei no Stack Overflow para perguntas com arquivo em lote contendo as palavras wmic Unicode e descobri que o cmd está de alguma forma escrevendo texto em chinês como saída .

A resposta aceita do dbenham não é boa, pois cria uma versão ANSI da saída Unicode do wmic.exe , mas o arquivo ANSI contém agora, de fato, 0D 0D 0A (= CR CR LF).

Melhor é a resposta de Dharma Leonardi, já que a solução com o uso do type comando resulta em uma conversão correta da saída Unicode para a saída ANSI, desde que a saída não contenha caracteres não disponíveis na página de código ANSI.

Mas depois de alterar o código do lote para processar a saída do wmic.exe com codificação ANSI, a linha com if defined BaseboardVersion sempre avaliada como true embora eu não conseguisse ver que a variável BaseboardVersion continha dados e, portanto, a próxima linha mostrava o status do eco.

Demorei algum tempo para descobrir com a inserção de set > Variables.txt acima da condição e procurando neste arquivo que no meu computador a string de versão é apenas um caractere de espaço único. O valor de Version era o único valor de todas as chaves sem uma string à direita do sinal de igual consistindo apenas em um único espaço.

Aqui está o arquivo de lote que finalmente funcionou no meu computador e produz a saída esperada:

 @echo off setlocal enabledelayedexpansion wmic.exe /OUTPUT:"%TEMP%\UnicodeData.tmp" baseboard get /format:list for /f "usebackq tokens=1,2* delims==" %%a in (`type "%TEMP%\UnicodeData.tmp"`) do ( if "%%a" == "Product" ( if not "%%b" == "" if not "%%b" == " " ( set "PlatformInfo=%%b" echo !PlatformInfo! echo !PlatformInfo!This overwrites the variable ) ) else if "%%a" == "Version" ( if not "%%b" == "" if not "%%b" == " " ( set "BaseboardVersion=%%b" echo !BaseboardVersion! echo !BaseboardVersion!This overwrites the variable ) ) ) del "%TEMP%\UnicodeData.tmp" endlocal 

Como já foi respondido, o problema é com as terminações de linha do wmic .

Você pode superar este problema se você não usar o fim da linha: wmic baseboard get Product,Version,Width usa três tokens: Produto, Versão e Largura (que é empy na maioria dos casos). Assim, a saída será: DX79SI,AAG28808-600, Estamos usando o token 1 e o token 2, ignorando o token 3 (isso teria o problema)

 set Platform=undefined set BaseboardVersion=undefined for /f "tokens=1,2 delims=," %%a in ('wmic baseboard get Product^,Version^,Width^|findstr "."') do ( set Platform=%%a set BaseboardVersion=%%b ) echo it is a %Platform% with Version %BaseboardVersion%. No overwriting 

Eu também adicionei delims=, no caso de qualquer uma das seqüências conter um espaço (não improvável com o product )

Intereting Posts