在BATCH中循环每个变量字符串中的字符

7

我想要遍历字符串中的每个字符。然而,我只知道如何使用以下代码遍历字符串中的每个单词:

(set /P MYTEXT=)<C:\MYTEXTFILE.txt

set MYEXAMPLE=%MYTEXT%
for %%x in (%MYEXAMPLE%) do (
ECHO DO SOMTHING
)

如何将其配置为按字符而不是按单词工作?
3个回答

7
这是一种简单直接的遍历字符串中每个字符的方法:

for循环可以用来实现:

@echo off
setlocal ENABLEDELAYEDEXPANSION

set /P mytext= < MYTEXTFILE.txt
echo Line is '%mytext%'

set pos=0
:NextChar
    echo Char %pos% is '!mytext:~%pos%,1!'
    set /a pos=pos+1
    if "!mytext:~%pos%,1!" NEQ "" goto NextChar

添加 setlocal enabledelayed expansion,否则下一个注释将是“不起作用” ;) (并且请务必删除 mytext= 之间的空格) - Stephan
@Stephan,谢谢。在我的系统上,“setlocal ENABLEDELAYEDEXPANSION”不需要,但是很好的建议。我测试了带空格和不带空格的SET,在我的系统上没有区别,并且我发现带空格更易读。我想可能是因为太多年没有真正做过批处理了。 - jimhark
什么?在 cmd 中空格确实会产生影响(set var = value 会将变量 %var<space>% 设置为 <space>value)。你使用什么系统(扩展)? - Stephan
@Stephan,哎呀!你说得对,感谢你纠正了这个问题。事情是这样的(我还保留着cmd窗口)。在命令行上工作时,我输入了SET /P命令行而没有任何额外的空格。但是我创建批处理文件时加入了额外的空格。当我测试批处理文件时,它似乎可以工作。(你可能已经看到了问题所在。)我现在发现我的环境变量中有“mytext=test”(来自命令行测试)和“mytext =test”(来自有缺陷的脚本)。文件内容没有改变,因此输出是正确的,但只是偶然的。我很少使用/P选项,只是认为它可以处理这个问题。 - jimhark
我已经这么想了。很高兴我们能够澄清这个问题。 - Stephan
显示剩余2条评论

4
据我所知,FOR不能进行逐字符迭代 - 一种可能的解决方法是构建以下循环:
@ECHO OFF
:: string terminator: chose something that won't show up in the input file
SET strterm=___ENDOFSTRING___
:: read first line of input file
SET /P mytext=<C:\MYTEXTFILE.txt
:: add string terminator to input
SET tmp=%mytext%%strterm%
:loop
:: get first character from input
SET char=%tmp:~0,1%
:: remove first character from input
SET tmp=%tmp:~1%
:: do something with %char%, e.g. simply print it out
ECHO char: %char%
:: repeat until only the string terminator is left
IF NOT "%tmp%" == "%strterm%" GOTO loop

注意:问题标题表明您想循环遍历“变量字符串中的每个字符”,这表明输入文件只包含一行内容,因为命令(set /P MYTEXT=)<C:\MYTEXTFILE.txt 仅会读取C:\MYTEXTFILE.txt的第一行。如果您想要遍历文件中的所有行,则解决方案会更加复杂,我建议您另外提出一个问题来询问。


是的,这回答了我所思考的问题,即我们不能为字符进行迭代。这也解释了为什么我的循环起作用以及在退出程序循环方面存在可能的解决方案。 - LabRat

0
下面是 splitStr 子程序的说明:
  • 将逐个打印出字符串中的每个字符
  • 无论延迟扩展的状态如何,都可以安全地调用
  • 没有超慢的 goto 循环
  • 处理回车符和换行符
  • errorLevel 设为字符串中字符的数量
@echo off & setLocal enableExtensions disableDelayedExpansion
(call;) %= sets errorLevel to 0 =%

set "testStr=uncopyrightable"
call :splitStr testStr
if errorLevel 1 (
    >&2 echo(string is %errorLevel% char(s^) in length
) else (
    >&2 echo(empty string
    goto die
) %= if =%
goto end

:die
(call) %= sets errorLevel to 1 =%
:end
endLocal & goto :EOF

:splitStr string=
:: outputs string one character per line
setLocal disableDelayedExpansion
set "var=%1"

set "chrCount=0" & if defined var for /f "delims=" %%A in ('
    cmd /v:on /q /c for /l %%I in (0 1 8190^) do ^
    if "!%var%:~%%I,1!" neq "" (^
    echo(:^!%var%:~%%I^,1^!^) else exit 0
') do (
    set /a chrCount+=1
    echo%%A
) %= for /f =%

endLocal & exit /b %chrCount%

那是一些巫术黑魔法... 这个程序会运行...并按顺序输出每个字符,带有/n。注意:只有在正确的情况下才能正常工作。任何与示例不同的变化都将失败(请参见下文)。此外,我试图修改脚本以为每个字符输出彩虹颜色...但它很脆弱...我无法让它在没有换行符的情况下回显。 call :splitStr testStr REM 正常工作!; call :splitStr "quotedtestStr" REM 不起作用!; set quotedtestStr="uncopyrightable" REM 不起作用!; call :splitStr %quotedtestStr% REM 不起作用!; - m1m1k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接