¿Cómo dividir una cadena por espacios en un archivo por lotes de Windows?

Supongamos que tengo una cadena “AAA BBB CCC DDD EEE FFF”.

¿Cómo puedo dividir la cadena y recuperar la enésima subcadena en un archivo por lotes?

El equivalente en C # sería

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

ver HELP FOR y ver los ejemplos

o prueba esto rápido

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

Tres posibles soluciones para iterar a través de las palabras de la cadena:

Versión 1:

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

Versión 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 

Versión 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 

La versión 1 no funciona cuando la cadena contiene caracteres comodín como ‘*’ o ‘?’.

Las versiones 1 y 3 tratan caracteres como ‘=’, ‘;’ o ‘,’ como separadores de palabras. Estos personajes tienen el mismo efecto que el personaje espacial.

Este es el único código que funcionó para mí:

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

salida:

 ddd 

El siguiente código dividirá una cadena con un número arbitrario de subcadenas:

 @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 

fácil

archivo por lotes:

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

línea de comando:

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

salida:

 1 2 3 

El siguiente código dividirá una cadena con N número de subcadenas con # valores separados. Puedes usar cualquier delimitador

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

o Powershell para una matriz indexada de 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 

Terminé con lo siguiente:

 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% 

Con esto puede parametrizar la entrada y el índice. Asegúrate de poner este código en un archivo bat.

 set a=AAA BBB CCC DDD EEE FFF set a=%a:~6,1% 

Este código encuentra el quinto carácter en la cadena. Si quisiera encontrar la novena cuerda, reemplazaría la 6 por 10 (agregue una).

Aquí hay una solución basada en una ” función ” que procesa cada carácter hasta que encuentra el carácter delimitador.

Es relativamente lento, pero al menos no es un desafío para la mente (excepto para la parte de la función).

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

puede usar vbscript en lugar de lote (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 

uso:

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

ACTUALIZACIÓN: Bueno, inicialmente publiqué la solución a un problema más difícil, para obtener una división completa de cualquier cadena con cualquier delimitador (simplemente cambiando delims ). Leí más las soluciones aceptadas que lo que OP quería, lo siento. Creo que esta vez cumplo con los requisitos originales:

  @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 

Una otra versión con una mejor interfaz de usuario:

  @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 

Ejemplos de salida:

 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 

Este es un archivo por lotes para dividir los directorios de la ruta:

 @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 

Segunda versión:

 @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 

3ra versión:

 @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 

Esto funciona para mí (solo un extracto de mi guión completo)

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

una variación más: busca el progtwig “cmd.exe” en la ruta actual e informa la primera coincidencia:

 @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