我在批处理脚本中反转字符串列表时遇到问题。假设我有一个列表L = string1,string2,string3我想获得反向列表L = string3,string2,string1。有任何想法吗??
在不知道您的输入是什么样的情况下,这可能是第一次尝试:
@ECHO OFF
SETLOCAL EnableDelayedExpansion
SET var=abc,def,ghi
SET rev=
:LOOP
IF NOT "!var!"=="" (
FOR /F "delims=, tokens=1,*" %%F IN ("!var!") DO (
SET rev=%%F,!rev!
SET var=%%G
)
) ELSE (
SET rev=!rev:~0,-1!
GOTO ENDLOOP
)
GOTO LOOP
:ENDLOOP
ECHO reversed list is: !rev!
编辑:根据要求,这里解释它是如何工作的:
var
是用逗号分隔的字符串的起始列表。
rev
将是反向字符串。在开头这个字符串是空的。
现在让我们来看看循环:
在每次迭代中,我们将字符串分成两部分:%%F
和%%G
。 %%F
将成为第一个逗号之前的所有内容,而%%G
将成为字符串的其余部分:FOR /F "delims=, tokens=1,*" %%F IN ("!var!")
。 delims=,
意味着我们使用逗号作为分隔符。 tokens=1,*
意味着第一个找到的子串将存储在%%F
中,而其余的将存储在%%G
中(%%F
是为第一个令牌定义的,所以Windows命令解释器会在G
,H
,I
等之后放置每个令牌 - 就像我们一样正在使用*
,一切都将落在%%G
)。最后,我们获取字符串的第一个标记(%%F
)并将,!rev!
附加到它。然后我们将剩余的字符串列表设置为第一个逗号后面的所有内容(%%G
)。
在第一次迭代中,此循环执行以下操作(伪代码):
var=abc,def,ghi
rev=
split the string into %%F=abc and %%G=def,ghi
set rev to %%F,rev //means abc,
set var to var but without the first token //means def,ghi
在第二次迭代中:
var=def,ghi
rev=abc,
split the string into %%F=def and %%G=ghi
set rev to %%F,rev //means def,abc
set var to var but without the first token //means ghi
在第三次迭代中:
var=ghi
rev=def,abc
split the string into %%F=ghi %%G=
set rev to %%F,rev //means ghi,def,abc,
set var to var but without the first token //means empty string
现在,在跳回:LOOP
后,if条件不再满足,因为!var!
已经从之前的abc,def,ghi
缩小到现在的空字符串。所以IF NOT !var!==""
变得虚假,我们跳到ELSE
条款。
还有一个问题:当我们通过预先附加原始列表中的第一个标记和逗号来构造我们的反向字符串时,我们将在反向字符串列表的末尾添加逗号:ghi,def,abc,
SET rev=!rev:~0,-1!
解决了这个问题。它从我们的字符串中获取一个“子字符串”,从索引0开始并在“结束-1”结束。所以这一行只是删除了字符串末尾的最后一个,
。然后我们跳到:ENDLOOP
。
您也可以使用这种更短/更简单的方法:
@echo off
setlocal EnableDelayedExpansion
set "L=string1,string2,string3"
echo Input =%L%
set "revL="
set "str=%L:,=" & set "revL=,!str!!revL!" & set "str=%"
set "revL=%str%%revL%"
echo Output=%revL%
此方法使用与其他答案相同的过程,但行数较少。如果你想知道这里发生了什么,删除@echo off
线并运行它。 ;)
这是一个批处理文件代码,假设L=string1,string2,string3
被分配给一个环境变量:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ListLine=L=string1,string2,string3"
for /F "tokens=1* delims==" %%I in ("%ListLine%") do (
set "LineBegin=%%I"
set "ListItems=%%J"
)
set "ReversedItems="
for %%I in (%ListItems%) do call set "ReversedItems=%%I,%%ReversedItems%%"
set "ListLine=%LineBegin%=%ReversedItems:~0,-1%"
echo %ListLine%
endlocal
Windows命令解释器在一个简单的FOR循环中解释字符串列表中的逗号,就像空格字符一样,因为在命令提示符窗口中运行没有@echo off
的批处理文件时可以看到它。因此,第二个FOR循环首先运行,string1
分配给循环变量I
,第二个用string2
,第三个用string3
。
命令CALL用于对命令SET进行双重处理,以避免使用延迟环境变量扩展的要求,如在命令提示符窗口中运行set /?
时的命令SET输出的帮助所解释的那样。
要了解使用的命令及其工作方式,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
call /?
echo /?
endlocal /?
for /?
set /?
setlocal /?
Aacini绝对拥有所有答案中最快的代码。这是一些使用类似SET技巧的较长代码。
@echo off
setlocal EnableDelayedExpansion
set i=1
set "x=abc,def,ghi"
set "x!i!=%x:,=" & set /A i+=1 & set "x!i!=%"
FOR /L %%G IN (%i%,-1,1) DO (
IF "%i%"=="%%G" (
set "reverse=!x%%G!"
) ELSE (
set "reverse=!reverse!,!x%%G!"
)
)
echo %reverse%
pause
只需对所有4个答案进行快速定时测试。第一个在3个逗号分隔字段的每一个中使用原始字符串3个字符。第二个在9个逗号分隔的字段中使用3个字符。每次我测试每次运行100次并计算平均值。差异可以忽略不计。
使用3x3平均100次尝试
Aacini 0.39254
Squashman 0.39851
Michael 0.3999
Mofi 0.40434
使用3x9平均100次尝试
Aacini 0.39925
Squashman 0.40278
Michael 0.41457
Mofi 0.43397