【问题标题】:How to loop through comma separated string in batch?如何批量循环逗号分隔的字符串?
【发布时间】:2013-06-18 00:01:05
【问题描述】:

窗户

根据帖子 (dos batch iterate through a delimited string),我在下面写了一个脚本,但没有按预期工作。

目标:给定字符串“Sun,Granite,Twilight”,我想在循环中获取每个主题值,以便对这些值进行一些处理。

当前输出不正确:

list = "Sun,Granite,Twilight"
file name is "Sun Granite Twilight"

第一次迭代应该是:

list = "Sun,Granite,Twilight"
file name is "Sun"

那么第二次迭代应该是“文件名是”Granite“等等。 我做错了什么?

代码:

set themes=Sun,Granite,Twilight

call :parse "%themes%"
goto :end

:parse
setlocal
set list=%1
echo list = %list%
for /F "delims=," %%f in ("%list%") do (
    rem if the item exist
    if not "%%f" == "" call :getLineNumber %%f
    rem if next item exist
    if not "%%g" == "" call :parse "%%g"
)
endlocal

:getLineNumber
setlocal
echo file name is %1
set filename=%1
endlocal

:end

【问题讨论】:

    标签: batch-file


    【解决方案1】:

    我会这样做:

    @echo off
    set themes=Sun,Granite,Twilight
    echo list = "%themes%"
    for %%a in ("%themes:,=" "%") do (
       echo file name is %%a
    )
    

    也就是说,将Sun,Granite,Twilight 更改为"Sun" "Granite" "Twilight",然后在常规(NO /F 选项)for 命令中处理用引号括起来的每个部分。这种方法比基于"delims=,"的迭代for /F循环要简单得多。

    【讨论】:

    • 当主题名称之一有空格时它是否也处理? (我现在被这个问题困住了..)
    • 我认为您甚至不需要用字符串替换逗号。见:stackoverflow.com/a/8086103/82211
    • @Justin:是的,但在这种情况下,解决方案不会“在主题名称之一有空格时也处理”。
    • 这真是太棒了!花了我一点理解,但基本上“for”命令默认情况下会 1)使用空格作为分隔符,2)将双引号项目理解为单个项目。这意味着for %%a in ("one" "two" "three and four") do echo %%a 将给出输出one\ntwo\three and four
    【解决方案2】:

    我接受了Aacini 的回答,只对其稍作修改以删除引号,以便可以像在所需命令中一样添加或删除引号。

    @echo off
    set themes=Hot Sun,Hard Granite,Shimmering Bright Twilight
    for %%a in ("%themes:,=" "%") do (
        echo %%~a
    )
    

    【讨论】:

      【解决方案3】:

      我对您的代码做了一些修改。

      1. 在子例程结束和主例程结束时需要 goto :eof,这样您就不会陷入子例程。
      2. tokens=1*(%%f 是第一个令牌;%%g 是该行的其余部分)
      3. ~ in set list=%~1 删除引号,这样引号就不会累积

        @echo off
        set themes=Sun,Granite,Twilight
        
        call :parse "%themes%"
        pause
        goto :eof
        
        :parse
        setlocal
        set list=%~1
        echo list = %list%
        for /F "tokens=1* delims=," %%f in ("%list%") do (
            rem if the item exist
            if not "%%f" == "" call :getLineNumber %%f
            rem if next item exist
            if not "%%g" == "" call :parse "%%g"
        )
        endlocal
        goto :eof
        
        :getLineNumber
        setlocal
        echo file name is %1
        set filename=%1
        goto :eof
        

      【讨论】:

      • 感谢您的提示!你能解释一下这行:set list=%~1 %~1 是什么意思?
      • 仅供我理解: :eof 是“内置”标签吗?因为我没有看到它定义。在子程序中它充当“返回”?奇怪的控制流,虽然:)
      • 是否出于某种原因使用 %%f 调用 :getLineNumber 并使用 "%%g" (在引号中)进行解析?
      • 没有其他原因是它在原始帖子中的方式,所以我没有更改它。如果我是从头开始做的,我也会引用 %%f 以避免将来如果字符串包含空格等出现麻烦。
      • 只是为了改进您的代码:在调用的返回点将 goto :eof 替换为 exit /b。它更简洁,避免在每个批次上写:eof 标签(如果你有很多),还允许通过放置exit / b ErrorValueErrorValue 必须是整数)返回错误。在调用后的最后一种方式中,您可以将错误视为异常处理,您可以在其中捕获它们并让主程序决定如何处理它。
      【解决方案4】:

      看起来它需要“tokens”关键字...

      @echo off
      set themes=Sun,Granite,Twilight
      
      call :parse "%themes%"
      goto :end
      
      :parse
      setlocal
      set list=%1
      
      for /F "delims=, tokens=1*" %%f in (%list%) do (
          rem if the item exist
          if not "%%f" == "" call :getLineNumber %%f
          rem if next item exist
          if not "%%g" == "" call :parse "%%g"
      )
      endlocal
      goto :end
      
      :getLineNumber
      setlocal
      echo file name is %1
      set filename=%1
      endlocal 
      
      :end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-15
        • 1970-01-01
        • 2013-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多