为什么/ f不能忽略空行?

时间:2015-07-09 11:07:24

标签: windows batch-file for-loop

我试图从批处理文件中的for /f循环中获取一个简单的值。

使用命令wmic path win32_localtime get dayofweek为我提供输出:

C:\sendemail>wmic path win32_localtime get dayofweek
DayOfWeek
1


C:\sendemail>

因此,使用以下批处理脚本,我应该能够返回" 1"的结果:

set cmd=wmic path win32_localtime get dayofweek
for /f "tokens=1 skip=1" %%Z in ('%cmd%') do set _myday=%%Z
echo Var is %_myday%

但是我没有,它将变量设置至少两次,如下所示:

C:\sendemail>set cmd=wmic path win32_localtime get dayofweek

C:\sendemail>for /F "tokens=1 skip=1" %Z in ('wmic path win32_localtime get dayofweek') do set _myday=%Z

C:\sendemail>set _myday=1

 :\sendemail>set _myday=

C:\sendemail>echo Var is
Var is

C:\sendemail>

起初,我想知道为什么,然后我意识到循环正在处理两个空行......它不应该是。根据这个:http://ss64.com/nt/for_cmd.html

  

Skip SKIP将从头开始跳过处理多行   文件。 SKIP包含空行,但在SKIP完成后,   FOR / F忽略(不迭代)空行。

要么,它不能正常工作,要么这些线不是空白的,并且充满了某些东西......

无论如何,我如何得到一周中的一天结果,而忽略其余部分?

5 个答案:

答案 0 :(得分:7)

关于行内容,是的,wmic的输出在每行的末尾包含for命令检测到的附加回车符。这就是非空行的原因。

您可以尝试使用

for /f "tokens=2 delims==" %%Z in ('
    wmic path win32_localtime get dayofweek /value
') do for /f %%Y in ("%%Z") do set "_myday=%%Y"

代码要求wmickey=value格式返回信息,并使用等号来标记输入记录。由于我们只请求第二个令牌,for将仅处理返回至少两个令牌的行,具有键(第一个令牌),等号(分隔符)和值(第二个令牌)的行

但是,该行末尾的附加回车符也包含在变量的值中。

当变量与普通语法(%_myday%)一起使用时,它不会被看到,但是如果延迟扩展(!_myday!),则会回显附加回车符。

要从变量中删除此附加字符,已在发布的代码中使用了第二个for命令。

答案 1 :(得分:2)

这种轻微的中间化将起作用:

@ECHO OFF
set cmd=wmic path win32_localtime get dayofweek
for /f "tokens=1 skip=1" %%Z in ('%cmd%') do (
    set _myday=%%Z
    GOTO BREAK
)
:BREAK
echo Var is %_myday%
PAUSE

读取所需的行后,只需跳出循环。

答案 2 :(得分:0)

以上是一个很好的方法,从一开始我就成功地应用了它。由于还需要捕获WMI变量并将其加载到环境变量中,因此我希望其中一些可以作为本机命令行。我偶然发现了这个...

for /F "skip=2 tokens=2 delims=," %%i IN ('wmic timezone get Bias /format:csv') do (echo var Bias=%%i; > %TZONEDB%mid.htm )  

核心是使用CSV格式可以跳过工作(没有尾随空格),并且可以轻松解析输出。

ed g

答案 3 :(得分:0)

我最近在这里讨论了这个问题,而以前的答案对我有帮助,我想检索几个变量以进行后续测试。最初,我使用类似于以下示例的代码(只是在explorer.exe上不使用,并且具有不同的变量名。已故意选择以下变量名以匹配后面的代码中的变量名限制)。 / p>

setlocal
for /F "skip=2 tokens=2,3,4 delims=," %%a in ('
  wmic /node:"MyFileServer-pc" process where Name^="explorer.exe"
    get HandleCount^,
        ParentProcessId^,
        ThreadCount
    /format:csv
') do (
  set ProcHandleCount=%%a
  set ProcParentProcessId=%%b
  set ProcThreadCount=%%c
)
echo HandleCount %ProcHandleCount%, ParentProcessID %ProcParentProcessId%, ThreadCount %ProcThreadCount%

但是,我不喜欢这种解决方案,因为wmic总是以内部迭代它们的顺序返回结果,而不管它们呈现给wmic命令的顺序如何,因此命令wmic process where Name^="explorer.exe" get ThreadCount^,HandleCount^,ParentProcessId仍然最后返回ThreadCount。这样一来,在获取多个参数值对时,先前的代码很容易出错,并且很难获得正确的排序。

因此,我改为使用以下代码,该代码可实现相同的结果,而无需关心wmic参数的顺序。无需担心订购也可以轻松添加其他参数。

setlocal
for /F "tokens=1,2delims==" %%a in ('
  wmic /node:"MyFileServer-pc" process where Name^="explorer.exe"
    get HandleCount^,
        ParentProcessId^,
        ThreadCount
    /value
') do @set Proc%%a^=%%b
echo HandleCount %ProcHandleCount%, ParentProcessID %ProcParentProcessId%, ThreadCount %ProcThreadCount%

在上面的代码中,变量名由来自wmic的每个返回的 parameter = value 对的 parameter 提供,并带有固定前缀,自动匹配返回的参数和值对。请注意,使用前缀(在这种情况下为'Proc'),而没有返回至少一个字符前缀,则wmic空行会导致错误。如果需要不同的环境变量名称,则第一种解决方案可以自由命名,并允许使用较短的名称,但是在需要多个值时更容易出错。 不管花多少钱,下面的代码都避免了变量前缀并使错误静音。通常需要更多唯一的变量名。

(
  for /F "tokens=1,2delims==" %%a in ('
    wmic /node:"MyFileServer-pc" process where Name^="explorer.exe" get HandleCount^,ParentProcessId^,ThreadCount /value
  ') do @set %%a=%%b
) 2>nul

这些示例使用wmic参数/ node:“ MyFileServer-pc”获取远程进程信息,但对于更简单的wmic命令同样有效。

答案 4 :(得分:0)

我在处理 wmic 输出时总是使用这个批处理模板:

setlocal enableextensions enabledelayedexpansion

for /f "delims and such" %%a in ('wmic path win32_localtime get dayofweek 2^>nul ^<nul') do (
  set VAR=%%a
  CALL :RMCRLF VAR
  if "!VAR!" NEQ "" (
    rem If we get here, then it's a non-empty line
    rem ... Do something ...
  )
)

GOTO :EOF
:RMCRLF
:: All this does is clean stray carriage returns/line feeds off of a variable,
:: which wmic is notorious for injecting into its output.
set RMCRVAR=%1
IF NOT DEFINED RMCRVAR GOTO :EOF
CALL set %RMCRVAR%=%%%RMCRVAR%%%
GOTO :EOF

这里的关键是“功能”(如果您愿意的话):RMCRLF。它将从变量中去除讨厌的回车符,以便您可以检查字符串是否真正为空,然后决定跳过空行。