【问题标题】:How to split a string by spaces in a Windows batch file?如何在 Windows 批处理文件中按空格拆分字符串?
【发布时间】:2010-12-14 23:46:44
【问题描述】:

假设我有一个字符串“AAA BBB CCC DDD EEE FFF”。

如何在批处理文件中拆分字符串并检索第 n 个子字符串?

C# 中的等价物是

"AAA BBB CCC DDD EEE FFF".Split()[n]

【问题讨论】:

    标签: windows batch-file split


    【解决方案1】:

    查看HELP FOR 并查看示例

    或快速尝试一下

     for /F %%a in ("AAA BBB CCC DDD EEE FFF") do echo %%c
    

    【讨论】:

    • 谢谢,这绝对有效。我希望能够参数化它,所以我可以获得第 n 个字符串,而不是......第三个字符串(%%c)。或第 4 个字符串 (%%d)。
    • 请注意,这也会在 '=' 处中断(可能还有其他)
    • 要么我做错了什么,要么这不再起作用。对我来说,它只输出“%c”
    • 对我来说,直到我在 /F 之后添加“tokens=1,2”,或者只设置了第一个变量 (%%a),它才起作用。
    • 看起来在 Windows 10 上不起作用。也许应该将其添加到回复中。
    【解决方案2】:

    您可以使用 vbscript 代替批处理(cmd.exe)

    Set objFS = CreateObject("Scripting.FileSystemObject")
    Set objArgs = WScript.Arguments
    str1 = objArgs(0)
    s=Split(str1," ")
    For i=LBound(s) To UBound(s)
        WScript.Echo s(i)
        WScript.Echo s(9) ' get the 10th element
    Next
    

    用法:

    c:\test> cscript /nologo test.vbs "AAA BBB CCC"
    

    【讨论】:

      【解决方案3】:

      简单

      批处理文件:

      FOR %%A IN (1 2 3) DO ECHO %%A
      

      命令行:

      FOR %A IN (1 2 3) DO ECHO %A
      

      输出:

      1
      2
      3
      

      【讨论】:

        【解决方案4】:

        以下代码将使用任意数量的子字符串拆分字符串:

        @echo off
        setlocal ENABLEDELAYEDEXPANSION
        
        REM Set a string with an arbitrary number of substrings separated by semi colons
        set teststring=The;rain;in;spain
        
        REM Do something with each substring
        :stringLOOP
            REM Stop when the string is empty
            if "!teststring!" EQU "" goto END
        
            for /f "delims=;" %%a in ("!teststring!") do set substring=%%a
        
                REM Do something with the substring - 
                REM we just echo it for the purposes of demo
                echo !substring!
        
        REM Now strip off the leading substring
        :striploop
            set stripchar=!teststring:~0,1!
            set teststring=!teststring:~1!
        
            if "!teststring!" EQU "" goto stringloop
        
            if "!stripchar!" NEQ ";" goto striploop
        
            goto stringloop
        )
        
        :END
        endlocal
        

        【讨论】:

        • 如果您删除 ENABLEDELAYEDEXPANSION 并将所有 ! 替换为 %,它似乎也可以正常工作。或者您是否特别需要该设置?
        【解决方案5】:
        set a=AAA BBB CCC DDD EEE FFF
        set a=%a:~6,1%
        

        此代码查找字符串中的第 5 个字符。 如果我想找到第 9 个字符串,我会将 6 替换为 10(加一个)。

        【讨论】:

          【解决方案6】:

          这是唯一对我有用的代码:

          for /f "tokens=4" %%G IN ("aaa bbb ccc ddd eee fff") DO echo %%G 
          

          输出:

          ddd
          

          【讨论】:

          • 这绝对应该是公认的答案。如果没有/f "tokens..,它在 Windows 10 上不起作用。
          • 第二个@Annie。尝试了以前的答案,没有这个都失败了。
          【解决方案7】:

          或 Powershell 用于 0 索引数组。

          PS C:\> "AAA BBB CCC DDD EEE FFF".Split()
          AAA
          BBB
          CCC
          DDD
          EEE
          FFF
          
          PS C:\> ("AAA BBB CCC DDD EEE FFF".Split())[0]
          AAA
          

          【讨论】:

            【解决方案8】:

            以下代码将拆分一个包含 N 个子字符串的字符串,其中 # 个分隔值。您可以使用任何分隔符

            @echo off
            if "%1" == "" goto error1
            
            set _myvar="%1"
            
            :FORLOOP
            For /F "tokens=1* delims=#" %%A IN (%_myvar%) DO (
                echo %%A
                set _myvar="%%B"
                if NOT "%_myvar%"=="" goto FORLOOP
            )
            
            goto endofprogram
            :error1
            echo You must provide Argument with # separated
            
            goto endofprogram
            :endofprogram
            

            【讨论】:

              【解决方案9】:

              遍历字符串单词的三种可能解决方案:

              版本 1:

              @echo off & setlocal
              set s=AAA BBB CCC DDD EEE FFF
              for %%a in (%s%) do echo %%a
              

              版本 2:

              @echo off & setlocal
              set s=AAA BBB CCC DDD EEE FFF
              set t=%s%
              :loop
              for /f "tokens=1*" %%a in ("%t%") do (
                 echo %%a
                 set t=%%b
                 )
              if defined t goto :loop
              

              版本 3:

              @echo off & setlocal
              set s=AAA BBB CCC DDD EEE FFF
              call :sub1 %s%
              exit /b
              :sub1
              if "%1"=="" exit /b
              echo %1
              shift
              goto :sub1
              

              当字符串包含“*”或“?”等通配符时,版本 1 不起作用。

              版本 1 和 3 将字符处理为 '='、';'或 ',' 作为单词分隔符。这些字符与空格字符的作用相同。

              【讨论】:

              • 版本 1 也适用于逗号分隔的列表,例如ABC,DEF,GHI,JKL
              • 太棒了!使用set /p s=<StringInFile.txt 将字符串从文件中取出,然后使用set t=%s%
              • 版本 2 最适合(大多数)任意分隔符。
              • 在版本 2 中:set t=%%b 到底在做什么?它从何而来?对不起,我不明白。请解释一下?谢谢。
              • @snahl 在版本 2 中,%%b 包含剩余的单词。 set t=%%b 从变量 t 中删除第一个单词。 “for”循环每次只执行一次,因为指定了/f 参数,而("%t%") 只是一行文本。 “goto :loop”是每个单词执行一次的实际循环。
              【解决方案10】:
              @echo off
              
              :: read a file line by line
              for /F  %%i in ('type data.csv') do (
                  echo %%i
                  :: and we extract four tokens, ; is the delimiter.
                  for /f "tokens=1,2,3,4 delims=;" %%a in ("%%i") do (
                      set first=%%a&set second=%%b&set third=%%c&set fourth=%%d
                      echo %first% and %second% and %third% and %fourth% 
                  )
              )
              

              【讨论】:

                【解决方案11】:

                这是一个基于“function”的解决方案,它处理每个字符直到找到分隔符。

                比较慢,但至少不是脑筋急转弯(功能部分除外)。

                :: Example #1:
                set data=aa bb cc
                echo Splitting off from "%data%":
                call :split_once "%data%" " " "left" "right"
                echo Split off: %left%
                echo Remaining: %right%
                echo.
                
                :: Example #2:
                echo List of paths in PATH env var:
                set paths=%PATH%
                :loop
                    call :split_once "%paths%" ";" "left" "paths"
                    if "%left%" equ "" goto loop_end
                    echo %left%
                goto loop
                :loop_end
                
                
                
                :: HERE BE FUNCTIONS
                goto :eof
                
                :: USAGE:
                ::   call :split_once "string to split once" "delimiter_char" "left_var" "right_var"
                :split_once
                    setlocal
                    set right=%~1
                    set delimiter_char=%~2
                    set left=
                
                    if "%right%" equ "" goto split_once_done
                
                    :split_once_loop
                        if "%right:~0,1%" equ "%delimiter_char%" set right=%right:~1%&& goto split_once_done
                        if "%right:~0,1%" neq "%delimiter_char%" set left=%left%%right:~0,1%
                        if "%right:~0,1%" neq "%delimiter_char%" set right=%right:~1%
                        if "%right%" equ "" goto split_once_done
                    goto split_once_loop
                
                    :split_once_done
                    endlocal & set %~3=%left%& set %~4=%right%
                goto:eof
                

                【讨论】:

                  【解决方案12】:

                  更新: 好吧,最初我发布了一个更困难问题的解决方案,用任何分隔符完全拆分任何字符串(只需更改 delims)。抱歉,我阅读的已接受解决方案比 OP 想要的要多。我认为这次我符合原来的要求:

                   @echo off
                   IF [%1] EQU [] echo get n ["user_string"] & goto :eof
                   set token=%1
                   set /a "token+=1"
                   set string=
                   IF [%2] NEQ [] set string=%2
                   IF [%2] EQU [] set string="AAA BBB CCC DDD EEE FFF"
                   FOR /F "tokens=%TOKEN%" %%G IN (%string%) DO echo %%~G
                  

                  具有更好用户界面的另一个版本:

                   @echo off
                   IF [%1] EQU [] echo USAGE: get ["user_string"] n & goto :eof
                   IF [%2] NEQ [] set string=%1 & set token=%2 & goto update_token
                   set string="AAA BBB CCC DDD EEE FFF"
                   set token=%1
                   :update_token
                   set /a "token+=1"
                   FOR /F "tokens=%TOKEN%" %%G IN (%string%) DO echo %%~G
                  

                  输出示例:

                  E:\utils\bat>get
                  USAGE: get ["user_string"] n
                  E:\utils\bat>get 5
                  FFF
                  E:\utils\bat>get 6
                  E:\utils\bat>get "Hello World" 1
                  World
                  

                  这是一个批处理文件,用于拆分路径的目录:

                  @echo off
                  set string="%PATH%"
                  :loop
                  FOR /F "tokens=1* delims=;" %%G IN (%string%) DO (
                      for /f "tokens=*" %%g in ("%%G") do echo %%g
                      set string="%%H"
                      )
                  if %string% NEQ "" goto :loop
                  

                  第二版:

                  @echo off
                  set string="%PATH%"
                  :loop 
                  FOR /F "tokens=1* delims=;" %%G IN (%string%) DO set line="%%G" & echo %line:"=% & set string="%%H"
                  if %string% NEQ "" goto :loop
                  

                  第三版:

                  @echo off
                  set string="%PATH%"
                  :loop
                  FOR /F "tokens=1* delims=;" %%G IN (%string%) DO CALL :sub "%%G" "%%H"
                  if %string% NEQ "" goto :loop
                  goto :eof
                  
                  :sub
                  set line=%1
                  echo %line:"=%
                  set string=%2
                  

                  【讨论】:

                  • 但这不符合问题
                  【解决方案13】:

                  这对我有用(只是我整个脚本的摘录)

                  choice /C 1234567H /M "Select an option or ctrl+C to cancel"
                  set _dpi=%ERRORLEVEL%
                  
                  if "%_dpi%" == "8" call :helpme && goto menu 
                  
                  for /F "tokens=%_dpi%,*" %%1 in ("032 060 064 096 0C8 0FA 12C") do set _dpi=%%1
                  echo _dpi:%_dpi%:
                  

                  【讨论】:

                    【解决方案14】:

                    我最终得到了以下结果:

                    set input=AAA BBB CCC DDD EEE FFF
                    set nth=4
                    for /F "tokens=%nth% delims= " %%a in ("%input%") do set nthstring=%%a
                    echo %nthstring%
                    

                    有了这个,你可以参数化输入和索引。确保将此代码放入 bat 文件中。

                    【讨论】:

                    • 这正是我在后期构建中从版本字符串中提取主要和次要版本所需要的。谢谢!
                    【解决方案15】:

                    另一种变体 - 在当前路径中查找程序“cmd.exe”并报告第一个匹配项:

                    @echo off
                    setlocal
                    setlocal enableextensions
                    setlocal enabledelayedexpansion
                    
                    set P=%PATH%
                    :pathloop
                    for /F "delims=; tokens=1*" %%f in ("!P!") do (
                        set F=%%f
                        if exist %%f\cmd.exe goto found
                        set P=%%g
                    )
                    if defined P goto pathloop
                    
                    echo path of cmd.exe was not found!
                    goto end
                    
                    :found
                    echo found cmd.exe at %F%
                    goto end
                    
                    :end
                    

                    【讨论】:

                    • 你的回答与问题无关
                    • 路径变量是一个联合字符串。将其拆分在示例中完成。并添加了一个小操作,向所有人展示如何在解析循环中完成实际工作。此工作示例显示了“首次点击即退出”反应。
                    【解决方案16】:

                    如果有人需要使用任何分隔符拆分字符串并将值存储在单独的变量中,这是我构建的脚本,

                    FOR /F "tokens=1,2 delims=x" %i in ("1920x1080") do (
                      set w=%i
                      set h=%j
                    )
                    echo %w%
                    echo %h%
                    

                    解释:'tokens' 定义了需要传递给 FOR 主体的元素,token 由字符 'x' 分隔。 所以在定界之后,第一个和第二个token被传递给body。在正文中,%i 指的是第一个标记,%j 指的是第二个标记。我们可以用 %k 来引用第三个令牌等等..

                    请在cmd中同时输入HELP FOR以获取详细解释。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2018-05-13
                      • 2017-11-14
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-05-20
                      相关资源
                      最近更新 更多