【问题标题】:Enumerating the delims of a FOR /F statement枚举 FOR /F 语句的分隔符
【发布时间】:2012-02-07 19:29:17
【问题描述】:

我有一个 FOR /F 语句,我希望它枚举命令正在解析的分隔符。例如:

FOR /F "delims=," %%A IN ("This,is,a,comma,delimited,sentence") DO (
    some command to enumerate delims
)
:OUT

我希望它考虑该句子中的每个分隔项。在这种情况下,它将输出6

编辑:我知道对每个人都进行检查还有很长的路要走。但我试图避免这种方法:

IF %%A == [] SET enum=0 && GOTO:OUT
IF %%B == [] SET enum=1 && GOTO:OUT

等等

【问题讨论】:

    标签: for-loop batch-file windows-xp enumerate


    【解决方案1】:

    无法在 FOR /F "delims=..." 命令中直接枚举项目。通常的方法是通过一个循环来计算一个项目,从句子中删除它并在有一个计数项目时重复。

    但是,根据特定的分隔符和句子中的其余字符,您可以使用 FOR 命令(不带 /F 选项),该命令将重复其代码,每个项目由标准批处理分隔符分隔,即逗号,分号和等号,除了空格。在您的特定示例中:

    SET ENUM=0
    FOR %%A IN (This,is,a,comma,delimited,sentence) DO SET /A ENUM+=1
    

    直接计算逗号分隔项的数量。如果分隔符是逗号、分号或等号以外的字符,可能的解决方案是三步法:

    1- Replace spaces, comma, semicolon and equal-sign for another know character(s).
    2- Replace the delimiter for any Batch standard delimiter (space, comma, etc).
    3- Use a simple FOR to directly enumerate the items.
    

    【讨论】:

    • 有趣,我从来不知道 FOR 可以做这样的事情。我一直认为标准的 FOR 循环仅用于迭代文件。最重要的是,它知道在逗号、分号和等号字符处停止阅读?
    【解决方案2】:

    有一种方法可以在 FOR /F "delims=..." 命令中直接枚举项目。
    您只需要在字符串中插入一些换行符。

    setlocal EnableDelayedExpansion
    set LF=^
    
    
    rem ** Two empty lines are required
    
    set count=0
    FOR /F "tokens=* delims=" %%a in ("item1!LF!item2!LF!item3") DO (
      set /a count+=1
      echo !count!: "%%a"
    )
    echo(
    set "CSV=This,is,a,comma,delimited,sentence"
    echo Or with comma separeted text: !CSV!
    for %%L in ("!LF!") do set "CSV=!CSV:,=%%~L!"
    set count=0
    FOR /F "tokens=* delims=" %%a in ("!CSV!") DO (
      set /a count+=1
      echo !count!: "%%a"
    )
    

    【讨论】:

    • 哇,太棒了!但是,我仍然不明白为什么这种方法有效。我一直认为FOR /F %%x IN ("string") 不是 repetitive 命令,而是 FOR 的一种特殊形式,它只是在标记中分隔一个字符串并执行一次命令。您的示例表明,在字符串中插入“delims=”和 LF(“tokens=”不是必需的)后,FOR /F 在重复命令中再次转换!这是对 LF char 的特殊处理(不是“错误”);否则,为什么其他分隔符的处理方式不同?
    • +1 - 我忘记了这个解决方案。这绝对是一个不错的选择。
    • @Aacini - 这不是特殊处理。 FOR /F 总是会在遇到 LF 时开始一个新的迭代,无论它从哪里获取输入。
    • @dbenham:这意味着上面的示例也适用于没有“tokens=* delims=" 选项:FOR /F %%a in ("item1!LF!item2!LF!item3") DO ...。处理字符串中的几行就像从文件中获取它们一样,并且可以使用“tokens = ... delims = ...”选项进一步处理每一行!有趣:)
    • @Acini:即使混合文件和字符串也可以。 for /f "delims=" %%A in (myFile.txt "hello") do echo %%A
    【解决方案3】:

    Aacini 建议使用简单的 FOR 代替 FOR /F 是一个很好的解决方案,除非字符串可能包含通配符 *?? 字符可以通过搜索和替换来保护,但是没有有效的方法来批量替换*

    如果遇到通配符问题,则可以恢复为在循环中使用 FOR /F 一次解析一个单词。大多数人使用 GOTO 来完成循环,因为您无法知道会找到多少个单词。但是 GOTO 比较慢。您可以通过对任意数量的项目使用外部 FOR 循环(不是 FOR /L)来实现显着的性能提升。在正文中,只要没有更多单词,您就可以使用 GOTO 退出循环。如果循环在没有用尽单词的情况下通过,您可以使用 GOTO 重新启动循环。包含 100 个项目的外循环每 100 个已解析的单词只会执行 1 个 GOTO。

    @echo off
    setlocal enableDelayedExpansion
    set "str=This,is,a,comma,delimited,sentence"
    set "L10=1 2 3 4 5 6 7 8 9 0"
    :loop - The outer FOR loop can handle 100 words before a single GOTO is needed
    for %%. in (%L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10%) do (
      for /f "tokens=1* delims=," %%A in ("!str!") do (
        echo %%A
        if "%%B" == "" goto :break
        set "str=%%B"
      )
    )
    goto :loop
    :break
    

    与所有 FOR 循环一样,如果在扩展 %%A 变量时启用延迟扩展,您必须担心 !^ 的损坏。

    FOR /L 不应用于外部循环,因为 FOR /L 总是完成对所有迭代的计数,即使您在主体中使用 GOTO。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-29
      • 1970-01-01
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      相关资源
      最近更新 更多