首页 > 解决方案 > 如何将 FOR 循环中的每个变量输出到它自己的文件

问题描述

我正在尝试使用 FOR 循环运行查询,并将查询输出的每个结果变量行放入它自己的文件中。

我似乎无法让延迟扩展变量按照我想要的方式运行。

基本上我正在查询安装在打印服务器上的打印机,我想要一个包含某些文本的 .bat 作业,并将结果输出到包含结果名称的多个文件。

我认为问题是我没有正确转义某些字符,或者我缺少 % 或 ! 在一个变量或它们的某种组合上。

@echo off
setlocal enabledelayedexpansion
FOR /F "tokens=1 delims=*" %%G IN ('wmic /node:PRINTSERVER printer get name') DO (

    SET printer=%%G
    SET printers=!printers: =!
    SET printers=!printers:Name=!
    ECHO ^(
        @ECHO OFF
        ECHO PLEASE WAIT WHILE YOUR PRINTER IS INSTALLED
        ECHO.
        ECHO ^"%windir%\system32\cscript %windir%\system32\prnmngr.vbs -ac -p \\PRINTSERVER\!printer!"^)>>!printer!.bat
)

endlocal

预期结果应该是多个名为PRINTERSHARENAME.bat

每个包含:

@ECHO OFF
ECHO PLEASE WAIT WHILE YOUR PRINTER IS INSTALLED
ECHO.
%windir%\system32\cscript %windir%\system32\prnmngr.vbs -ac -p "\\PRINTSERVER\PRINTERSHARENAME"

编辑

我将分享更多我的代码。wmic 输出包含必须去除的空格,所以这就是我使用 enabledelayedexpansion 的原因

编辑2

这是我的 wmic 命令的输出(请注意,我在上面的代码中删除了尾随空格以及命令末尾的单词 'Name' 和一个空行):

C:\Users\bleepbloop>wmic /node:PRNTSVR printer get name
Name
PRINTER1                          
PRINTER2                              
OFFICEPRINTER                        

编辑3

好的,我快接近了。这是重现的代码,使用下面的答案:

(
echo Here is my first line
echo Here is my second line
echo Here is my third line
)>"textfile.txt"

FOR /F "delims=" %%G IN ('TYPE textfile.txt') DO (
    (
        ECHO @ECHO OFF
        ECHO ECHO PLEASE WAIT WHILE YOUR PRINTER IS INSTALLED
        ECHO ECHO.
        ECHO "%%windir%%\system32\cscript" "%%windir%%\system32\prnmngr.vbs" -ac -p \\PRINTSERVER\%%G
    )>%%G.bat
)

这按预期工作,并为我提供了 3 个名为

Here is my first line.bat
Here is my second line.bat
Here is my third line.bat

但是现在我想从 textfile.txt 输出的变量中删除所有空格,为此我认为我需要使用延迟扩展?

所以我想要:

Hereismyfirstline.bat
Hereismysecondline.bat
Hereismythirdline.bat

我想我需要通过使用 enabledelayedexpansion 并在 FOR 循环中插入以下内容来做到这一点:

SET variable=%%G
SET variable=!variable: =!

然后我必须将变量正确地插入循环中。仍然不确定如何。

我要文件

Hereismyfirstline.bat

包含装有

@ECHO OFF
ECHO PLEASE WAIT WHILE YOUR PRINTER IS INSTALLED
ECHO.
"%windir%\system32\cscript" "%windir%\system32\prnmngr.vbs" -ac -p \\PRINTSERVER\Hereismyfirstline

和下一个文件

Hereismysecondline.bat

包含装有:

@ECHO OFF
ECHO PLEASE WAIT WHILE YOUR PRINTER IS INSTALLED
ECHO.
"%windir%\system32\cscript" "%windir%\system32\prnmngr.vbs" -ac -p \\PRINTSERVER\Hereismysecondline

标签: batch-filefor-loopvariablesoutput

解决方案


我建议为此任务使用此批处理代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "skip=1 eol=| tokens=*" %%I in ('%SystemRoot%\System32\wbem\wmic.exe /node:PRINTSERVER printer get name 2^>nul') do (
    for /F "eol=| delims=   " %%J in ("%%I") do (
        set Printer=%%~nxJ
        if defined Printer (
            echo @echo off
            echo echo PLEASE WAIT WHILE YOUR PRINTER IS INSTALLED
            echo echo/
            echo "%%SystemRoot%%\system32\cscript.exe" "%%SystemRoot%%\system32\prnmngr.vbs" -ac -p "\\PRINTSERVER\%%~nxJ"
        )>"%%~nxJ.bat"
    )
)
endlocal

注意:delims=第二个for命令行之后必须是水平制表符,而不是 Web 浏览器根据制表符的 HTML 标准显示的一个或多个空格。

处理输出wmic是有问题的,因为此应用程序输出的数据始终使用 UTF-16 Little Endian 编码进行 Unicode 编码,并且for在正确处理此 Unicode 输出时存在怪癖。有关更多详细信息,请参见示例如何在解析输出时更正变量覆盖错误行为?

外部for处理wmic跳过包含标题的第一行的输出Name。对于所有其他非空行,在将行的其余部分分配给指定的循环变量之前,所有前导I正常空格和水平制表符都将被删除,即使在以分号开头非常不寻常的情况下也是如此。|打印机名称中不允许出现,但;尽管从未见过以;.

以水平制表符为分隔符的内部for处理可以包含一个或多个空格的打印机名称,但不能包含制表符。删除了所有尾随水平制表符的打印机名称被分配给指定的循环变量J

剩下的字符串是带有尾随普通空格的打印机名称。Windows 通常会阻止创建带有尾随空格的文件。因此,仅Printer使用%%~nxJ打印机名称而不使用尾随空格将其分配给环境变量。但是此命令保留打印机名称中的空格。

for由处理输出的怪癖导致的单个回车导致删除wmic环境变量Printer而不是用回车定义。

因此,如果环境变量Printer确实使用不包含、一个甚至多个空格,但不包含前导空格/制表符和尾随空格/制表符的打印机名称定义,则可以使用分配给循环变量J的打印机名称来创建批处理文件批处理文件和批处理文件名使用%%~nxJ.

因此,不需要延迟的环境变量扩展,这使得该批处理文件也适用于包含感叹号的打印机名称。

另请参阅 DosTips 论坛主题ECHO。无法提供文本或空行 - 而是使用 ECHO/写入创建的批处理文件echo/而不是echo..

此批处理代码使用内部循环内的延迟扩展来删除批处理文件名的打印机名称中的所有空格。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "skip=1 eol=| tokens=*" %%I in ('%SystemRoot%\System32\wbem\wmic.exe /node:PRINTSERVER printer get name 2^>nul') do (
    for /F "eol=| delims=   " %%J in ("%%I") do (
        set "Printer=%%~nxJ"
        if defined Printer (
            setlocal EnableDelayedExpansion
            set "BatchFileName=!Printer: =!"
            (
                echo @echo off
                echo echo PLEASE WAIT WHILE YOUR PRINTER IS INSTALLED
                echo echo/
                echo "%%SystemRoot%%\system32\cscript.exe" "%%SystemRoot%%\system32\prnmngr.vbs" -ac -p "\\PRINTSERVER\!Printer!"
            )>"!BatchFileName!.bat"
            endlocal
        )
    )
)
endlocal

像任何其他包含空格或这些字符之一的文件/文件夹名称一样,将整个批处理文件名用双引号括起来,运行文件名中包含一个或多个空格的批处理文件绝对没有问题&()[]{}^=;!'+,`~。但是第二个批处理文件代码表明可以创建文件名中没有空格的批处理文件,而打印机名称中的感叹号仍然被正确处理。

setlocal由于使用和endlocal在循环内部,此代码比第一个代码慢。阅读此答案以了解有关命令的详细信息setlocalendlocal以及在后台每次使用这两个命令时会发生什么,从而使第二个变体比第一个变体慢。

注意:批处理文件中的打印机名称带有空格。只是批处理文件名没有空格。但如果需要,这可以很容易地改变。


推荐阅读