批处理:如何在parsing输出时纠正variables覆盖不当行为

batch file中,我正在检查Baseboard信息,其中包含以下内容:
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 ) ) ) 

上面的问题:当echo'd出来时,variables被覆盖,而不是附加到。
输出:

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

我想要的是:

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

我已经花了几个小时(而且会继续这样做),但是希望别人遇到这个问题。 我希望任何遇到这个parsing问题的人都能在将来避免它。

由此产生的额外问题是它似乎打破了条件逻辑。

更新
在所有的帮助之后,我想出了这个解决scheme:

 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%. 

是的,你有问题,但这不是你的想法。

wmic有一个特殊的行为:在每行输出结尾有一个附加的回车符,即每行以0x0d 0x0d 0x0a结尾0x0d 0x0d 0x0a

这个附加的回车函数存储在你的变量中,当你回到控制台时,你得到的数据和回车,所以,如果变量后面跟着更多的文本,因为光标已经定位在行的开始处回车),这个文本被回显在前面的回显数据上。

怎么解决?

 @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 ) ) ) 

在这种情况下,在不改变你的代码逻辑的情况下,可以使用for /f命令的附加来消除附加的回车

哇,真的很难找出这里发生了什么事情。

首先,我不能相信批处理文件执行会发生什么。

在Windows XP SP3 x86上执行了很多试用之后

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

并用文件管理器Total Commander的查看器查看文件Output.txt 我看到顶部有两条空行,但这并不重要。 所以我继续进行其他的试验。

后来我在文本编辑器UltraEdit中打开Output.txt ,立即在状态栏U-DOS上看到输出文件是用UTF-16编码的,有DOS行结束符的小尾数。 我切换到十六进制编辑模式,可以看到

 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=. 

所以输出文件确实是一个UTF-16 LE BOM的Unicode文件。 没有CR CR LF。 所有线路终端都是正确的CR LF对(回车+换行)。

现在我搜索堆栈溢出的问题与批处理文件包含单词wmic Unicode ,发现CMD以某种方式写中文文本作为输出 。

dbenham接受的答案不好,因为它创建了wmic.exe的Unicode输出的ANSI版本,但ANSI文件现在确实包含0D 0D 0A(= CR CR LF)。

更好的是Dharma Leonardi的答案是,只要输出不包含在ANSI代码页中不可用的字符,使用命令type结果将Unicode输出正确转换为ANSI输出的解决方案。

但是,在更改批处理代码以使用ANSI编码处理wmic.exe输出后, if defined BaseboardVersion值总是为true,尽管我看不到包含任何数据的变量BaseboardVersion ,因此下一行导致显示回显状态。

我花了一段时间才发现,在条件之上插入set > Variables.txt并查看这个文件,在我的电脑上版本字符串只是一个空格字符。 版本的值是所有密钥的唯一值,没有只包含单个空格的等号的字符串右边。

这是最后在我的电脑上工作的批处理文件,并产生预期的输出:

 @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 

如已经回答的那样,问题在于wmic的结束。

如果不使用行尾,则可以解决此问题: wmic baseboard get Product,Version,Width使用三个令牌:Product,Version和Width(在大多数情况下为empy)。 所以输出将是: DX79SI,AAG28808-600,我们使用令牌1和令牌2,忽略令牌3(这会有问题)

 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 

我还添加了delims=,以防万一任何字符串包含一个空格(不太可能与product