如何在 Windows 批处理文件中按空格分割字符串?

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

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

C # 中的等价物是

"AAA BBB CCC DDD EEE FFF".Split()[n]
352508 次浏览

参见 HELP FOR和示例

或者试试这个

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

可以使用 vbscript 而不是 batch (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"

放松

批处理文件:

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

命令行:

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

产出:

1
2
3

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

@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
set a=AAA BBB CCC DDD EEE FFF
set a=%a:~6,1%

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

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

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

产出:

ddd

或者用于0索引数组的 Powershell。

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

下面的代码将使用 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

迭代字符串的单词有三种可能的解决方案:

版本一:

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

第二版:

@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

第三版:

@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将“ =”、“ ;”或“”等字符作为单词分隔符。这些字符与空格字符具有相同的效果。

@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%
)
)

下面是一个基于“ 功能”的解决方案,它处理每个字符,直到找到分隔符字符为止。

这是相对缓慢的,但至少不是一个脑筋急转弯(除了功能部分)。

:: 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

更新: 好吧,最初我发布了一个更难的问题的解决方案,得到一个完整的分割任何字符串与任何分隔符(只是改变 分隔线)。对不起,我读了更多被接受的解决方案,而不是 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

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

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%:

我得到了以下结论:

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 文件。

还有一个变体——它在当前路径中查找程序“ 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

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

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

说明: ‘ tokens’定义了需要传递给 FOR 主体的元素,令牌由字符‘ x’分隔。 因此,在分隔之后,第一个和第二个令牌被传递给主体。在主体% 1表示第一个标记,% 2表示第二个标记。我们可以使用% k 来引用第3个标记,以此类推。.

也请键入 帮助在 cmd 得到一个详细的说明。