为什么此批处理脚本中的 FOR /f 循环评估空行?
我正在尝试编写一个批处理脚本,该脚本获取(除其他外)计算机拥有的所有磁盘驱动器的列表。基本代码如下所示:
REM Build the list of disk drives to monitor
SETLOCAL enabledelayedexpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\\|"
)
我显然构建了两个格式略有不同的列表,以供稍后使用。然而,当我运行此命令时,我得到的输出看起来像这样:
C|D|E||
C:\\|D:\\|E:\\|:\\|
现在,我希望在这两种情况下都有尾随管道,并且我可以管理它,但我真的很困惑为什么其中有一个额外的空白条目。如果我手动运行 wmic
命令,我可以看到输出末尾确实有一个空行,但我的理解是 /f
是专门应该的忽略空行。
如果我打开 ECHO
,看起来最后一行只是作为回车符/换行符或类似的内容出现。有办法做我期待的事情吗?我错过了什么吗?我尝试在循环中编写一个 if
条件来排除最后一行,但它......很时髦并且从未起作用。我感谢任何/所有帮助。
I'm trying to write a batch script that obtains (among other things) a list of all of the disk drives the computer has. The basic code looks something like this:
REM Build the list of disk drives to monitor
SETLOCAL enabledelayedexpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\\|"
)
I pretty obviously build two lists with slightly different formats for use later. When I run this, however, the output I get looks something like this:
C|D|E||
C:\\|D:\\|E:\\|:\\|
Now, I expect the trailing pipe in both cases and I can manage that, but I'm really confused why there is an extra blank entry in there. If I run the wmic
command manually, I can see that there is indeed a blank line at the end of the output, but my understanding is that /f
was specifically supposed to ignore blank lines.
If I turn ECHO
on, it looks like that last line is just coming in as a carriage return/newline or similar. Is there a way to do what I'm expecting? Am I missing something? I tried to write an if
condition in the loop to exclude this last line, but it was... funky and never worked. I appreciate any/all help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我刚过来这个话题。我一直在使用 findstr /v 来排除空行:
I just came over this topic. I've been using findstr /v to exclude empty lines:
在这种情况下,最后一次迭代不会生成空项,并且您只能通过
echo %DISK_DATABASES%
获得C|D|E||
的输出,但是
echo !DISK_DATABASES!
会输出||D|E|
??这是因为最后一个元素是单个
字符。并且
字符在百分比扩展后会被直接删除,但不会延迟扩展。您可以避免这种情况,使用百分比扩展来删除它们
In this case the last iteration produces not an empty item, and you get your output of
C|D|E||
only withecho %DISK_DATABASES%
,but
echo !DISK_DATABASES!
will output||D|E|
??That's because the last element is a single
<CR>
character.And
<CR>
characters are directly removed after the percent expansion, but not with delayed expansion.You could avoid this, using the percent expansion to remove them
根据 http://ss64.com/nt/for_f.html
因此看来 WMIC 和 FOR 不能很好地结合在一起。
According to http://ss64.com/nt/for_f.html
So it appears that WMIC and FOR don't play nice together.
我发现了一种更有效、更可靠的方法来从每行末尾去除不需要的
。没有临时文件,也不需要 CALL。我不明白 FOR /F 如何将 WMIC unicode 输出转换为 ASCII 的机制。通常 FOR /F 无法读取 unicode。但无论它如何工作,每个转换后的行都以
结尾。 FOR /F 在每个
处换行,然后如果该行的最后一个字符是
,则会删除最后一个;
,在本例中留下不需要的
。解决方案是简单地将每一行再传递一个 FOR /F :-)
这种方法比使用正常扩展更可靠,因为您不必担心引用或转义特殊字符。例如,使用正常扩展的 CALL 方法无法处理像
"this & that" & 这样的字符串。另一个
。但是这个方法对于这样的字符串是没有问题的。I discovered a more efficient and more reliable method to strip the unwanted
<CR>
from the end of each line. No temp file, and no CALL needed.I don't understand the mechanism of how FOR /F converts the WMIC unicode output into ASCII. Normally FOR /F cannot read unicode. But however it works, each converted line ends with
<CR><CR><LF>
. FOR /F breaks lines at each<LF>
, and then if the last character in the line is<CR>
it strips that last<CR>
, in this case leaving behind the unwanted<CR>
.The solution is to simply pass each line through one more FOR /F :-)
This method is more reliable then using normal expansion because you don't have to worry about quoting or escaping special characters. For example, The CALL method that uses normal expansion cannot handle a string like
"this & that" & the other
. But this method has no problem with such a string.添加 <代码>^| findstr . 你只会得到非空行
Add
^| findstr .
and you will get only not blank lines我处理此问题的标准习惯用法是将 WMIC 的输出写入临时文件,然后使用 TYPE(将 UTF16 转换为 ASCII)将其输入 FOR,如下所示:
My standard idiom for dealing with this is to write the output from WMIC to a temp file, then use TYPE (which reduces UTF16 to ASCII) to feed that into FOR, like this:
运行以下命令:
输出将为:
请注意,不会有多余的行。
Run the following command:
Output will be:
Note that there will be no extra lines.