我想将一个字符串分成两部分,而不使用任何for循环。
例如,我在变量中包含字符串:
str=45:abc
我想在变量中获取45
,在另一个变量中获得abc
。是否可以在批处理文件中使用?
模式就像somenumber:somestring
答案 0 :(得分:17)
你可以用不同的方式分割str。
for循环,你不想使用它。
使用*
(匹配任何内容,直到......)后端部分很容易
set "var2=%str:*:=%"
领导部分可以用令人讨厌的技巧来完成
set "var1=%str::="^&REM #%
需要插入符号以逃避&符号,
如此有效地将结肠替换为"&REM #
所以在你的情况下,你在更换后得到了线
set "var1=4567"&REM #abcde
这被分为两个命令
set "var1=4567"
REM #abcde`
完整的代码在这里:
set "str=4567:abcde"
echo %str%
set "var1=%str::="^&REM #%
set "var2=%str:*:=%"
echo var1=%var1% var2=%var2%
编辑2:更稳定的领导部分
感谢Dave使用换行的想法 对于带引号和特殊字符的内容,REM技术不是很稳定 但是使用换行技巧存在一个更稳定的版本,当split参数长于单个字符时也可以使用。
@echo off
setlocal enableDelayedExpansion
set ^"str=456789#$#abc"
for /F "delims=" %%a in (^"!str:#$#^=^
!^") do (
set "lead=%%a"
goto :break
)
:break
echo !lead!
解决方案3:Adbented dbenhams回答
Dbenham在他的解决方案中使用了带管道的换行 这看起来有点过于复杂 由于解决方案使用的事实是,解析器在未转义的换行符之后删除了其余的行(当在special character phase之前或之后找到它时)。
首先,冒号字符被替换为具有延迟扩展替换的换行符
这是允许的,换行现在是变量的一部分
然后线set lead=%lead%
剥去尾随部分
最好不要在这里使用扩展语法,因为如果引号是字符串的一部分,set "lead=%lead%"
会中断。
setlocal enableDelayedExpansion
set "str=45:abc"
set ^"lead=!str::=^
!"
set lead=%lead%
echo "!lead!"
答案 1 :(得分:4)
你可以试试这个。如果它固定在冒号左边的数字将总是2&在右边将是3.然后下面的代码应该工作假设您的str具有值。
set "str=45:abc"
echo %str%
set var1=%str:~0,2%
set var2=%str:~3,3%
echo %var1% %var2%
让我发布。 :)
答案 2 :(得分:3)
避免使用FOR循环似乎毫无意义,但它确实使问题变得有趣。
正如杰布指出的那样,使用!str:*:=!
可以轻松获取尾随部分。
棘手的一点是主要部分。这是jeb解决方案的替代方案。
您可以使用以下语法将换行符插入变量以代替:
setlocal enableDelayedExpansion
set "str=45:abc"
echo !str::=^
!
- 输出 -
45
abc
上一个!
上方的空行很重要。
我不知道为什么,但是当上述输出通过管道发送到命令时,只保留第一行。因此输出可以通过管道传输到与任何行匹配的FINDSTR,并将结果定向到一个文件,然后可以使用SET / P将其读入变量。
在使用SET / P之前必须消除第2行,因为SET / P无法将<LF>
识别为行终止符 - 它只识别<CR><LF>
。
这是一个完整的解决方案:
@echo off
setlocal enableDelayedExpansion
set "str=45:abc"
echo(!str::=^
!|findstr "^" >test.tmp
<test.tmp set /p "var1="
del test.tmp
set "var2=!str:*:=!"
echo var1=!var1! var2=!var2!
<强>更新强>
我相信我已经弄明白为什么第二行会从输出中删除:)
它与Windows cmd.exe处理管道的方式有关,每个端由新的CMD.EXE线程处理。有关相关问题,请参阅Why does delayed expansion fail when inside a piped block of code?,其中包含来自jeb的精彩答案。
只要查看管道命令的左侧,我相信它会被解析(在内存中)成一个看起来像
的语句C:\Windows\system32\cmd.exe /S /D /c" echo {delayedExpansionExpression}"
我使用{delayedExpansionExpression}
来表示多行搜索并替换尚未发生的扩展。
接下来,我认为实际上扩展了变量表达式,并且通过搜索和替换将行拆分为两行:
C:\Windows\system32\cmd.exe /S /D /c" echo 43
abc"
只有这样才能执行命令,并且通过正常的cmd.exe规则,命令在换行符处结束。引用的命令字符串缺少结束引号,但解析器不关心它。
我仍然感到困惑的部分是abc"
会发生什么?我原以为会尝试执行它,导致出现错误消息,如 'abc“'不被识别为内部或外部命令,可操作程序或批处理文件。 但相反,它似乎只是迷失在以太中。
注意 - jeb的第3条评论解释了原因:)
没有FOR的安全版
我的原始解决方案无法使用this & that:cats & dogs
之类的字符串。这是一个没有FOR的变体,几乎可以用于任何字符串,除了字符串长度限制和尾随控制字符将从前导部分剥离。
@echo off
setlocal enableDelayedExpansion
set "str=this & that:cats & dogs"
set ^"str2=!str::=^
!^"
cmd /v:on /c echo ^^!str2^^!|findstr /v "$" >test.tmp
<test.tmp set /p "var1="
del test.tmp
set "var2=!str:*:=!"
echo var1=!var1! var2=!var2!
我将扩展延迟到新的CMD线程,并使用FINDSTR正则表达式的怪癖,$
仅匹配以<cr>
结尾的行。第一行没有它,第二行没有。 /v
选项会反转结果。
答案 3 :(得分:3)
是的,我知道这是一个非常古老的话题,但我刚发现它,我无法抗拒发布我的解决方案的诱惑:
@echo off
setlocal
set "str=45:abc"
set "var1=%str::=" & set "var2=%"
echo var1="%var1%" var2="%var2%"
您可以阅读此方法的完整详情here。
答案 4 :(得分:0)
这是一个没有讨厌的技巧的解决方案
REM accepts userID@host
setlocal enableDelayedExpansion
set "str=%1"
set "host=%str:*@=%"
for /F "tokens=1 delims=@" %%F IN ("%str%") do set "user=%%F"
echo user@host = %user%@%host%
endlocal
答案 5 :(得分:0)
在人们发布用于分割变量的各种各样的mehots之后,我不妨发布我自己的方法,不仅允许一个而且几个分裂出来变量,由相同的符号表示,这是REM-Method无法实现的(我使用了一段时间,感谢@jeb)。
使用下面的方法,第二行中定义的字符串分为三部分:
setlocal EnableDelayedExpansion
set fulline=one/two/three or/more
set fulline=%fulline%//
REM above line prevents unexpected results when input string has less than two /
set line2=%fulline:*/=%
set line3=%line2:*/=%
set line1=!fulline:/%line2%=!
set line2=!line2:/%line3%=!
setlocal DisableDelayedExpansion
echo."%line1%"
echo."%line2%"
echo."%line3%"
输出:
"one"
"two"
"three or/more//"
我建议将最后这样创建的字符串分区用作剩余“安全”分裂字符的“bin”。