batch:延迟参数回显后的不需要的换行符

时间:2014-04-17 15:33:34

标签: windows batch-file

这是使用wmic.exe打印包含不同系统信息的文本的批处理的一部分。在一个部分,我使用调用和标签来制作硬盘信息的自动参数我必须使用参数内的参数来使其工作。这仅适用于启用延迟扩展。因此在for / f循环中包含回显文件的回传线路并且延迟扩展的代码在扩展结束后直接回应换行符!我不知道为什么或如何解决这个问题。我已经决定用批处理这样做了,是的,我知道这在vbs脚本中更容易用wmi做。任何帮助都很有帮助

@echo off

for /f "skip=2 delims=" %%a in ('wmic diskdrive get medialoaded') do call :getdisk

for /f "skip=2 delims=" %%a in ('wmic diskdrive get medialoaded') do call :setdisk

>%tmp%\t.x echo wscript.echo round^(wscript.arguments^(0^) / ^(1024 * 1024 * 1024^), 1^)

for /f "skip=2 delims=" %%a in ('wmic diskdrive get medialoaded') do call :numdisk

goto:eof

:getdisk
set /a disk=%disk%+1
goto:eof

:setdisk
if not defined numreset set /a numreset=%disk%-1
if not defined num (set num=0) else (set /a num=%num%+1)
for /f "tokens=1-10 delims==" %%a in ('wmic diskdrive %num% get interfacetype^,model^,size /format:list') do set %%a%num%=%%b
if "%num%"=="%numreset%" set "num="
goto:eof

:numdisk
if not defined num (set num=0) else (set /a num=%num%+1)
set /a hdd=%num%+1
setlocal enabledelayedexpansion
set interfacetype=interfacetype%num%
set mediatype=mediatype%num%
set size=size%num%
if "%disk%" geq "%num%" >>hdd.txt echo HDD %hdd%:      index %num%
if "%disk%" geq "%num%" >>hdd.txt echo InterFace:  !%interfacetype%!
if "%disk%" geq "%num%" >>hdd.txt echo MediaType:  !%mediatype%!
if "%disk%" geq "%num%" for /f %%a in ('cscript //nologo //e:vbscript %tmp%\t.x "!%size%!"') do set sizegb=%%a
if "%disk%" geq "%num%" >>hdd.txt echo Size:       !%size%! b ^(%sizegb% gb^)
if "%disk%" geq "%num%" >>hdd.txt echo.
endlocal
goto:eof

解决方法

由于换行符在扩展变量中,因此删除它很简单:

::before:
!%var%!

::after:
!%var%:~0,-1!

1 个答案:

答案 0 :(得分:3)

OMG!那段代码是可怕的,不必要的复杂和低效 - 我几乎无法遵循逻辑。为了让它发挥作用,你有更多的权力,但我想我可以告诉你一个更好的方法:)

首先,它不是额外的换行符或换行符(<LF>,十六进制0x0A,十进制10),它是一个额外的回车符(<CR>,十六进制0x0D​​,十进制13)。不需要的字符是FOR / F如何与WMIC的unicode输出交互的奇怪工件。 FOR / F尝试将unicode转换为ANSI,但不知何故用<CR><CR><LF>终止每行输出。 FOR / F在<LF>之前结束每一行,然后删除最后一个字符<CR>,这会在每行的末尾留下一个不需要的尾随<CR>

消除不需要的字符的一个简单方法是使用额外的FOR / F,因为如果它是<CR>它将删除最后一个字符:

for /f "delims=" %%A in ('WMIC ...') do for /f "yourOptions" %%B in ("%%A") do ...

这种方法的好处是它不需要延迟扩展。

但是由于你已经在使用延迟扩展,你设置变量然后使用子字符串操作来修剪掉最后一个字符的方法完全正常。


现在开发一个更合理的代码库来获得您想要的结果:

无需多次解析WMIC输出 - 您可以在仅执行一次WMIC的单个FOR / F循环中执行所有操作。

您可以使用CSV代替LIST格式。这将磁盘驱动器的所有必需值放在一行,逗号分隔。唯一的缺点是可能存在空值,这会导致FOR / F解析出现问题,连续分隔符被视为一个,因此可能会错过令牌。诀窍是使用搜索和替换来在每个令牌周围加上引号。然后缺失值变为,"",,可以通过第二个FOR / F轻松解析。使用%%~A稍后删除每个令牌的引号。

你的WMIC命令获取了你不使用的Model,你的输出引用了你没有得到的Media Type。我修改了代码来获取和输出两者。

您为每个磁盘索引运行不同的WMIC,但WMIC DISKDRIVE提供了您可以获得的INDEX值,因此为什么不使用它。我的输出没有按索引顺序排序,但所有信息都在那里。如果真的需要,可以添加额外的代码来按索引对结果进行排序。

将外部FOR / F括在括号中然后将该输出重定向一次会更有效。

最后,您无需使用临时VBS脚本进行数学运算。很容易嵌入并在批处理脚本中调用JScript。

@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScrpt comment

::************ Batch portion ***********
@echo off
setlocal enableDelayedExpansion
set cnt=0
(
  for /f "skip=2 delims=" %%A in (
    '"wmic diskdrive get interfacetype,model,size,index,mediaType /format:csv"'
  ) do (
    set "ln=%%A"
    set "ln=!ln:~0,-1!"
    set "ln="!ln:,=","!""
    set /a cnt+=1
    for /f "tokens=2-6 delims=," %%B in ("!ln!") do (
      echo HDD !cnt!: Index %%~B
      echo Interface: %%~C
      echo Model: %%~E
      echo Media: %%~D
      set "size="
      if %%F neq "" for /f %%N in (
        'cscript //E:JScript //nologo "%~f0" "Math.round(%%~F/1024/1024/1024*10)/10"'
      ) do set "size=%%N GiB"
      echo  Size: !size!
      echo(
    )
  )
)>hdd.txt
exit /b

************ JScript portion ***********/
WScript.StdOut.WriteLine(eval(WScript.Arguments.Unnamed(0)));

编辑:我刚刚意识到模型描述可能包含逗号,这会导致FOR / F解析CSV格式的问题。所以这是另一种恢复到List格式的解决方案。事实证明代码更简单:)

我使用第二个FOR / F技巧删除不需要的尾随<CR>

@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScrpt comment

::************ Batch portion ***********
@echo off
setlocal enableDelayedExpansion
set cnt=0
(
  for /f "delims=" %%L in (
    '"wmic diskdrive get interfaceType,model,size,index,mediaType /format:list"'
  ) do for /f "tokens=1* delims==" %%A in ("%%L") do (
    if %%A equ Index (
      if !cnt! gtr 0 echo(
      set /a cnt+=1
      echo HDD !cnt!: Index %%B
    ) else if %%A equ Size (
      set "size="
      if "%%B" neq "" for /f %%N in (
        'cscript //E:JScript //nologo "%~f0" "Math.round(%%B/1024/1024/1024*10)/10"'
      ) do set "size=%%N GiB"
      echo %%A: !size!
    ) else echo %%A: %%B
  )
)>hdd.txt
exit /b

************ JScript portion ***********/
WScript.StdOut.WriteLine(eval(WScript.Arguments.Unnamed(0)));
相关问题