【问题标题】:How can I output each variable from a FOR loop to it's own file如何将 FOR 循环中的每个变量输出到它自己的文件
【发布时间】:2019-12-16 09:55:39
【问题描述】:

我正在尝试使用 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 输出包含必须去除的空格,所以这就是我使用 enableelayedexpansion 的原因

EDIT2

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

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

EDIT3

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

(
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-file for-loop variables output


    【解决方案1】:

    我建议这个任务的批处理代码:

    @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
    

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

    处理wmic 的输出是有问题的,因为此应用程序输出的数据总是使用 UTF-16 Little Endian 编码的 Unicode 编码,而for 在正确处理此 Unicode 输出时有一个怪癖。有关更多详细信息,请参阅例如 How to correct variable overwriting misbehavior when parsing output?

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

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

    剩余的字符串是带有尾随正常空格的打印机名称。 Windows 通常会阻止创建带有尾随空格的文件。出于这个原因,分配给环境变量Printer 使用%%~nxJ 只是打印机名称,没有尾随空格。但是此命令会保留打印机名称中的空格。

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

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

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

    另请参阅 DosTips 论坛主题 ECHO. FAILS to give text or blank line - Instead use ECHO/,了解写入创建的批处理文件 echo/ 而不是 echo. 的原因。

    此批处理代码在内部循环中使用delayed expansion 删除批处理文件名的打印机名称中的所有空格。

    @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,此代码比第一个代码慢。阅读 this answer 了解有关命令 setlocal 和 endlocal 的详细信息,以及在后台每次使用这两个命令时会发生什么,从而使第二个变体比第一个变体慢。

    注意:批处理文件中的打印机名称带有空格。只是批处理文件名没有空格。但如果需要,可以轻松更改。

    【讨论】:

    • 这个批处理文件对我没有任何作用,也没有输出任何文件,但是你很有帮助,我确实学到了一些东西。我还尝试删除 wmic 命令并在该空间中使用“type textfile.txt”,其中 textfile.txt 包含 3 行带空格的文本,后 2 行输出为 .bat 文件,而第一行不是。我怀疑你在 wmic 编码的正确轨道上导致了一个问题,因为我在尝试处理我在普通文本文件上没有得到的 wmic 输出时遇到了其他错误。谢谢你的帮助,我用另一种方式找到名字。
    【解决方案2】:

    括号可以对命令进行分组,但不能拆分参数。所以,不要使用ECHO (...,而是:

        SET printer=%%G
        (
            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\!printer!"
        )>!printer!.bat
    

    将>> 替换为>,这将为每台打印机创建新文件,而不是 将更多命令附加到现有文件。

    还注意到您不需要延迟扩展,可能"delims=" 更合适。 总体而言,您的代码可能会被重写为:

    FOR /F "delims=" %%G IN ('wmic /node:PRINTSERVER printer get name') 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
    )
    

    【讨论】:

    • 此代码适用于 'type filename.txt' 但不适用于 wmic 命令,因为必须从输出中去除空格。这就是为什么我认为我需要 enabledelayedexpansion 是为了去除空格。请查看我的问题编辑,我已经澄清了很多。感谢分享这个,它帮助我走得更远,但还没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 2021-11-05
    • 2017-06-11
    相关资源
    最近更新 更多