最后删除 space WMIC 的 属性 值并添加另一个字符串

Remove space at last Property value of WMIC and add another string

抱歉我的英语不好。 我想删除 WMIC 的最后 属性 值处的 space 并添加另一个字符串。

del /f /q "GPU.txt"
for /f "skip=2 tokens=2,3,4 delims=," %%a in ('"wmic path Win32_VideoController get Caption,CurrentHorizontalResolution,CurrentVerticalResolution /format:csv"') do (
    SETLOCAL EnableDelayedExpansion
    For %%# in (*) do (
        SET var=%%~n#
        Set MyVar=!var!
        set MyVar=!MyVar: =!
    )
    echo %%a (%%b x !MyVar!)>>"GPU.txt"
)

没有可显示的内容。 谢谢

为什么有问题的代码不起作用?

  1. 请阅读this answer了解命令SETLOCALENDLOCAL的详细信息。在 FOR 循环中使用 SETLOCAL 强烈建议在同一个 ENDLOCAL 中使用 ENDLOCAL =]FOR 循环或循环执行期间可能发生堆栈溢出。这不会发生在这里,因为循环迭代次数不多,但是 ENDLOCAL 应该在同样包含 FOR 的循环中使用 SETLOCAL.

  2. 问题代码中的
  3. For %%# in (*) do处理当前目录中non-hidden个文件的每个文件名。没有文件扩展名的文件名分配给环境变量var。接下来,这个变量被分配给另一个变量 MyVar 而不做任何修改,除了行 Set MyVar=!var! 将包含尾随 space 或制表符。最后,所有 space 都从环境变量 MyVar 的字符串值中删除,这是一个文件名。

    我不知道这个用于处理当前目录中文件名的 FOR 循环与视频控制器名称和当前水平和垂直分辨率有什么关系。

    我建议阅读 Why is no string output with 'echo %var%' after using 'set var = text' on command line?

  4. 上的答案
  5. 命令行echo %%a (%%b x !MyVar!)>>"GPU.txt"中的右圆括号)被解释为第一个FOR命令块的结尾。有必要使用 ^ 转义 ) 并使用 echo %%a (%%b x !MyVar!^)>>"GPU.txt" 来获得由 cmd.exe 解释为文字字符的右括号,以在解析整个过程时由 echo 输出在第一个 FOR 命令行上以 ( 开头的命令块。

  6. wmic.exe 输出文本 UTF-16 Little Endian(每个字符两个字节)而不是 ANSI 编码(每个字符一个字节)。 FOR 分别 cmd.exe 在解释 Unicode 编码字符流时存在错误,例如在 How to correct variable overwriting misbehavior when parsing output?

    中有详细解释

    你认为垂直分辨率值末尾的 space 实际上是附加到该值的回车 return,因为命令对 wmic.exe 的 Unicode 输出处理错误FOR分别cmd.exe.

什么是有效代码,为什么有效?

此任务的一个可能解决方案是使用此批处理代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
(for /F "tokens=2-4 delims=," %%I in ('%SystemRoot%\System32\wbem\wmic.exe PATH Win32_VideoController GET Caption^,CurrentHorizontalResolution^,CurrentVerticalResolution /FORMAT:CSV ^| %SystemRoot%\System32\findstr.exe /R ",[0123456789][0123456789]*$"') do (
    set /A CurrentVerticalResolution=%%K
    call echo %%I (%%J x %%CurrentVerticalResolution%%^)
))>"GPU.txt"
endlocal

Windows Management Instrumentation 命令的 Unicode 输出被重定向到 FINDSTR,它过滤以逗号和一位或多位数字结尾的行的输出。因此 CSV 输出的标题行被删除,视频控制器行以 ,, 结尾,没有当前水平和垂直分辨率的值。除了具有正确值的 CSV 行之外,我的 Windows 计算机上也输出了这样的 CSV 行。

尽管使用 findstr.exe.

过滤了 wmic.exe 的输出,但在当前垂直分辨率的最后一个值末尾出现错误回车 return 的问题仍然存在

因此,分配给循环变量 K 的当前垂直分辨率值不会直接在 echo 命令行中使用,因为这会导致 ) 覆盖视频控制器的第一个字符标题字符串。这里使用的解决方案是使用算术表达式将当前垂直分辨率值分配给环境变量CurrentVerticalResolution。整数值末尾的回车符 return 被解释为表达式末尾的任何其他白色 space 字符,这意味着它会被 cmd.exe 忽略。所以环境变量 CurrentVerticalResolution 赋值时末尾没有不需要的回车 return。

上面的代码通过使用命令CALL来解析来避免使用SETLOCALENDLOCAL echo 命令行两次,解释如下:

How does the Windows Command Interpreter (CMD.EXE) parse scripts?

带有转义 )%%CurrentVerticalResolution%% 而不是 %CurrentVerticalResolution%echo 命令行已经在第一次解析 echo 时修改为下面的行在执行命令 FOR:

之前按 cmd.exe 的命令行
call echo %I (%J x %CurrentVerticalResolution%)

剩余的环境变量引用%CurrentVerticalResolution%在执行命令ECHO之前被这个环境变量的当前值替换,因为命令在循环的每次迭代中进行第二次解析呼叫.

也可以在 FOR 循环中使用:

setlocal EnableDelayedExpansion
echo %%I (%%J x !CurrentVerticalResolution!^)
endlocal