【问题标题】:Batch: using upper for loop parameter in lower one批处理:在下一个中使用上 for 循环参数
【发布时间】:2016-04-29 15:43:28
【问题描述】:

我试图运行的命令是:

::%items% is defined elsewhere and is the amount of items per line in the file
    FOR /F "usebackq tokens=1-%items% delims=," %%1 IN (`TYPE %TextFile%`) DO (

        FOR /l %%a in (%items%,-1,1) do (
            set /a "number=%%a"
            echo !number!

:: This is the main command I believe im having issues with
        set word!number!=%%!number!


        echo !word1!
        echo !word2!
        echo !word3!
    )
    set /a "lineused%randomline%=1"
    goto exitloop
)
:exitloop
pause

现在我要做的是设置名为 wordX 的变量,其中 X 是令牌的编号。编辑:基本上,尝试使用下部 for 循环中运行的 %% 变量。 我可以输入所有的行

set word1=%%1
set word2=%%2
set word3=%%3

但这会破坏我正在尝试构建的多功能系统的目的。 在这种情况下,文本文件 (%TextFile%) 的格式就是:

line1i1,line1i2
line2i1,line2i2

但我需要它也可以工作,例如:

line1i1,line1i2,line1i3,line1i4
line2i1,line2i2,line2i3,line1i4

【问题讨论】:

    标签: batch-file for-loop


    【解决方案1】:

    有趣的想法,但是因为 FOR 变量扩展发生在之前延迟扩展,所以这行不通。您需要一种方法来获得额外一轮的 FOR 变量扩展。

    您可以调用子程序,然后使用虚拟 FOR 循环重新建立 FOR 上下文。只要您在 FOR 循环上下文中, FOR 变量就在范围内是全局的。因此,您的子例程可以访问之前定义的 FOR 变量。

    ...
    ...
        FOR /F "tokens=1-%items% delims=," %%1 IN ('TYPE %TextFile%') DO (
    
            FOR /l %%a in (%items%,-1,1) do call :set %%a
    
            echo !word1!
            echo !word2!
            echo !word3!
        )
    ...
    ...
    exit /b
    
    :set
    for %%. in (.) do set "word%1=%%%1"
    exit /b
    

    上述方法有效,但我不喜欢它,因为 CALL 很昂贵(慢)。当您只有几个 CALL 时,这通常不是问题。但在这种情况下,CALL 处于紧密循环中 - 每列一个乘以文件中的行数。哎哟!

    如果您真的想对您的 SET 语句进行参数化,并且想要获得不错的性能,那么您可以定义一个动态“宏”。只需将所需的命令存储在变量中,然后在循环中执行变量的内容。

    另请注意,以上内容仅限于 9 个项目(如果您以 0 而不是 1 开头,则为 10 个)。如果您使用字母和查找字符串,很容易将支持的项目数扩展到 26。

    最后,您的动态 FOR 位于某个带括号的块中。大概您的项目是在块之外定义的,否则 %items% 无法在 FOR /F 定义中使用。 SET 宏必须使用常规扩展进行扩展,因此应在定义 ITEMS 的同时定义它 - 在外循环之外。

    set /a items=3
    ::Define SET macro
    set "v= ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    set "set="
    for /l %%N in (1 1 %items%) do set "set=!set!&set "word%%N=%%!v:~%%N,1!""
    set "set=!set:~1!"
    
    FOR ... some loop ... DO (
      ...
      ...
    
      FOR /F "tokens=1-%items% delims=," %%A IN ('TYPE %TextFile%') DO (
        %set%
        echo !word1!
        echo !word2!
        echo !word3!
      )
    
      ...
      ...
    )
    

    如果必须在外循环内设置ITEMS 变量,则必须在循环外调用以建立内FOR / F 循环。

    【讨论】:

    • 如果items 确实在外部for 循环中定义,则需要在内部for /L 循环中进行felayed 扩展(您的第二种方法)...
    • @aschipfl - 是的,我认为这只是证实了我的大脑有些奇怪:-) 我也是一名音乐家,不久前我醒来时脑海中出现了一首歌曲19/8 节奏循环。 soundcloud.com/dave-benham/dave-benham-trio-dance-of-the-crane
    【解决方案2】:

    请注意,您不需要TYPE 来获取文件内容,FOR 命令本身可以遍历文件内容

    你可以试试这样的:

    @echo off
    setlocal enabledelayedexpansion
    
    set "TextFile=textfile.txt"
    set /a "lineNum=0"
    set /a "i=0"
    for /f "tokens=*" %%a in (%TextFile%) do (
            set /a lineNum=!line_num! + 1
            set "line=%%a"
            for %%b in ("!line:,=" "!") do (
                set /a "i=!i!+1"
                set /a "wordNum=!lineNum! * !i!
                set "word!wordNum!=%%b"
        )
    )
    echo !word1!
    echo !word2!
    echo !word3!
    

    给定一个包含内容的文件:

    aaa,bbb,ccc,ddd
    eee,fff,ggg,hhh
    

    输出将是:

    "aaa"
    "bbb"
    ... and so on
    

    要删除引号,请在 set "word!wordNum! 行的内部 FOR 中使用 %%~b

    另请注意,您甚至不需要定义每行的项目数!

    希望对你有帮助, 干杯!

    【讨论】:

    • 这可以在许多情况下工作,但如果任何行包含*?" 字符,它将失败。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多