views:

569

answers:

1

I have a delimited list of IPs I'd like to process individually. The list length is unknown ahead of time. How do I split and process each item in the list?

@echo off
set servers=127.0.0.1,192.168.0.1,10.100.0.1

FOR /f "tokens=* delims=," %%a IN ("%servers%") DO call :sub %%a

:sub
    echo In subroutine
    echo %1
exit /b

Outputs:

In subroutine
127.0.0.1
In subroutine
ECHO is off.

Update: Using Franci's answer as reference, here's the solution:

@echo off
set servers=127.0.0.1,192.168.0.1,10.100.0.1

call :parse "%servers%"
goto :end


:parse
setlocal
set list=%1
set list=%list:"=%
FOR /f "tokens=1* delims=," %%a IN ("%list%") DO (
  if not "%%a" == "" call :sub %%a
  if not "%%b" == "" call :parse "%%b"
)
endlocal
exit /b

:sub
setlocal
echo In subroutine
echo %1
endlocal
exit /b

:end

Outputs:

In subroutine
127.0.0.1
In subroutine
192.168.0.1
In subroutine
10.100.0.1
+2  A: 

Update: If the number of items in the list is not known, it is still possible to parse all items with simple recursion on the head of the list. (I've changed the IPs to simple numbers for simplicity of the list)

Finally that Lisp class I took 18 years ago paid off...

@echo off
setlocal

set servers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24

echo %servers%

call :parse "%servers%"

goto :eos

:parse

set list=%1
set list=%list:"=%

FOR /f "tokens=1* delims=," %%a IN ("%list%") DO (
  if not "%%a" == "" call :sub %%a
  if not "%%b" == "" call :parse "%%b"
)

goto :eos

:sub

echo %1

goto :eos

:eos
endlocal
Franci Penov
This doesn't work -- it just prints "b" and "c" after the first IP address. Besides, the OP stated that the number of inputs would be unknown ahead of time. This may not be possible in a pure DOS batch file -- but I"m glad to know that I'm not the only one still using them!
harpo
my mistake, forgot to change the * to the token numbers. And you are right - if the number of tokens is not known ahead of time, it's not possible in standard Windows shell scripting.
Franci Penov
Exactly harpo. The servers variable serves simple as an example. In practice (in my case, this script will be used as part of the deployment scheme), the servers variable is read as a user parameter. Knowing I ask the impossible is also good so I can move on to alternative approaches.
bjax-bjax
Now see what you guys made me do. I actually pulled out my ages old copy of Windows NT Shell Scripting (the most used book in my technical library) to refresh my rusty shell scripting skills... :-) A little bit of recursion goes a long way to solving problems like this.
Franci Penov
Excellent. Recursion to the rescue!
bjax-bjax
Sure enough -- pretty amazing!
harpo
@harpo: That batch already uses features that didn't exist back in DOS times. I'm pretty sure the OP wanted a Windows batch file anyway.
Joey
Franci: You can probably make the `call :parse` in the loop a `goto parse` which should exit the loop instead of recursing. You don't really need recursion here anyway and stack space is limited.
Joey
@Johannes is right, this can be easily transformed into an iterative solution.
Franci Penov