dos批处理迭代分隔的字符串

bja*_*jax 36 command-line batch-file

我有一个我想单独处理的IP分隔列表.列表长度提前未知.如何拆分和处理列表中的每个项目?

@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
Run Code Online (Sandbox Code Playgroud)

输出:

In subroutine
127.0.0.1
In subroutine
ECHO is off.
Run Code Online (Sandbox Code Playgroud)

更新: 使用Franci的答案作为参考,这是解决方案:

@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
Run Code Online (Sandbox Code Playgroud)

输出:

In subroutine
127.0.0.1
In subroutine
192.168.0.1
In subroutine
10.100.0.1
Run Code Online (Sandbox Code Playgroud)

Mat*_*ict 94

for命令默认处理多个分隔符.在这种情况下,你可以做到

@echo off

set servers=127.0.0.1,192.168.0.1,10.100.0.1

for %%i in (%servers%) do (
  echo %%i
)
Run Code Online (Sandbox Code Playgroud)

如果您遇到本机支持的分隔符,您可以执行替换以首先准备字符串,使其格式正确

@echo off

set servers=127.0.0.1@192.168.0.1@10.100.0.1
set servers=%servers:@=,%

for %%i in (%servers%) do (
  echo %%i
)
Run Code Online (Sandbox Code Playgroud)

一旦遍历列表中的特定数量的项目,使用递归调用就有可能耗尽堆栈空间.同样测试它,递归模式似乎运行得慢一点.


Fra*_*nov 28

更新:如果列表中的项目数目未知,则仍可以使用列表头部的简单递归来解析所有项目.(为了简化列表,我已将IP更改为简单数字)

最后,我18年前的Lisp课程得到了回报......

@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
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用 - 它只是在第一个IP地址后打印"b"和"c".此外,OP表示提前输入的数量是未知的.这在纯DOS批处理文件中可能是不可能的 - 但我很高兴知道我不是唯一仍在使用它们的人! (2认同)
  • 现在看看你们让我做了什么.我实际上拿出了我的老版本的Windows NT Shell Scripting(我的技术库中最常用的书)来刷新我生锈的shell脚本技能... :-)一点点的递归对于解决像这样的问题有很长的路要走. (2认同)

小智 7

我不敢相信这这么复杂!似乎每个人都想频繁地分割一个字符串,而不知道其中有多少个标记,也不按行解析它。通常,人们似乎正在写入文件,然后单步执行它或使用像其他方法一样的多子方法。真是一团糟!

这是我的解决方案。它更容易遵循并且内联工作,即没有子例程。建立一个文件名列表或其他内容,然后逐步浏览它们,而不必将它们写入临时文件,确保没有文件写入冲突,删除临时文件等,这很好。另外,我不知道如何返回来自 sub 的值就像它是一个函数一样 - 我认为你不能。因此,每次你想做这样的事情时,你都必须继续写 2 个 subs 以及我在这里看到的其他答案 - 一个提供另一个答案。我的方法可以让您轻松创建列表,并在整个脚本中根据需要多次单步执行它们。

setlocal enableextensions enabledelayedexpansion

set SomeList=
set SomeList=!SomeList!a;
set SomeList=!SomeList!b;
set SomeList=!SomeList!c;
set SomeList=!SomeList!d;
set SomeList=!SomeList!e;
set SomeList=!SomeList!f;
set SomeList=!SomeList!g;

set List=!SomeList!
:ProcessList
FOR /f "tokens=1* delims=;" %%a IN ("!List!") DO ( 
  if "%%a" NEQ "" ( 
      echo %%a
  )
  if "%%b" NEQ "" (
      set List=%%b
      goto :ProcessList
  )
)
Run Code Online (Sandbox Code Playgroud)

输出:

a
b
c
d
e
f
g
Run Code Online (Sandbox Code Playgroud)

显然你可以用有用的东西来交换回声。


kyb*_*kos 7

困难在于for命令用于处理通常在文件中找到的多行文本字符串.我发现这个问题的最佳解决方案是将您的字符串修改为多行.

rem You need to enable delayed expansion, otherwise the new line will interfere
rem with the for command.
setlocal ENABLEDELAYEDEXPANSION
rem The following three lines escape a new line and put it in a variable for
rem later.
rem The empty lines are important!
set newline=^


set list=jim alf fred
for /F %%i in ("%list: =!newline!%") do (echo item is %%i)
Run Code Online (Sandbox Code Playgroud)

最后一个for循环将迭代空格分隔变量中的项.它通过用换行符替换列表变量中的空格,然后执行正常的循环来完成它.


Aac*_*ini 5

是的,我知道这是一个非常古老的主题,但我最近发现了一个有趣的技巧,可以以更简单的方式执行请求的拆分。这里是:

set n=1
set "server[!n!]=%servers:,=" & set /A n+=1 & set "server[!n!]=%"
Run Code Online (Sandbox Code Playgroud)

这两行将servers字符串拆分为server 数组,并定义了n已创建元素数量的变量。这样,您只需要使用for /L从 1 到 的命令%n%即可处理所有元素。这是完整的代码:

@echo off
setlocal EnableDelayedExpansion

set servers=127.0.0.1,192.168.0.1,10.100.0.1

set n=1
set "server[!n!]=%servers:,=" & set /A n+=1 & set "server[!n!]=%"

for /L %%i in (1,1,%n%) do echo Process server: !server[%%i]!
Run Code Online (Sandbox Code Playgroud)

这种方法不仅比任何其他基于for命令的方法更简单、更快,而且还允许直接使用多字符字符串作为分隔符。

您可以在这篇文章中阅读有关拆分方法的更多详细信息。