批处理文件:在嵌套循环中处理列表元素
batch file: working with list elements in nested loop
我一直在尝试让以下批处理脚本正常工作,看来我需要请教在 Batch 方面具有更多专业知识的人,因为我不知道为什么它一直无法正常工作。我的目的是交换列表 VAR
的两个元素:
@echo off
rem enable delayed expansion, required for extended usage of environment variables
SETLOCAL EnableDelayedExpansion
SETLOCAL EnableExtensions
set VAR=abcd efgh ijkl mnopq rstvw qwert yxcva rtzewrw yxvys
set fst=qwert
set scnd=rstvw
call :test %VAR%
:test
SETLOCAL
for %%i in (%*) do (
for %%j in (%* %%i) do (
if %scnd% equ %%i (
if %fst% equ %%j (
echo "gotcha before swapping: " "i: " %%i "j: " %%j
set tempor=%%i
set i=%%j
set j=!tempor!
echo "gotcha after swapping: " "i: " !i! "j: " !j!
set List=!List! %%j %%i
)
)
)
set List=!List! %%i
echo "List: " !List!
)
ENDLOCAL
goto :eof
:ende
我试图让列表看起来像这样:
abcd efgh ijkl mnopq qwert rstvw yxcva rtzewrw yxvys
交换 fst(第一个元素)和 scnd(第二个元素)的位置。
输出是这样的:"List: " abcd efgh ijkl mnopq qwert rstvw rstvw qwert yxcva rtzewrw yxvys
,所以我得到了 qwert
和 rstvw
的双重输入,我知道这是因为 set List=!List! %%i
的位置.
至少我知道,交换 正在工作。
但我的问题是:如果我把它放在 else
分支中,就像我通常在任何其他脚本语言中所做的那样,列表将在每个循环中填充 %%i
和 %%j
,所以它变得无用....
您的问题似乎是 %%i
和 %i%
完全是 不同的 变量。您不能为 %%i
赋值 - 只有 for
命令可以。
您似乎在尝试执行插入排序来构建排序的字符串列表。您的代码结构可能是为解决问题而进行的编辑的遗留问题,但正如所发布的那样,例程将通过流程重新输入。此外,由于例程 :test
包含在 setlocal/endlocal 括号中,因此对 list
的更改在 :test
例程之外将不可见。连续使用两个 setlocal
命令会建立两个 嵌套 本地环境。 两个选项可以在一个setlocal
语句中同时指定。请注意,setlocal
不是一个开关 - 它建立了一个本地环境(是的,微软已被要求建立 delayed expansion
等作为单独的 swtich 类型操作,如 echo on/off
)
另请注意,您生成的列表包含前导 space。我用以下替代例程遵循了这个想法:
快速眼动
SET "list2="
for %%i in (%*) do (
REM %%i has each element in turn
SET "startlist= "
SET "endlist= "
IF defined list2 for %%j in (!list2!) do (
IF "%%j" lss "%%i" (
SET "startlist=!startlist!%%j "
) ELSE (
SET "endlist=!endlist!%%j "
)
)
SET "list2=!startlist!%%i!endlist:~0,-1!"
)
ECHO "List2:" %list2%+
(我在末尾添加了一个 +
以显示字符串的结尾 list2
。
是 - 在原始问题中指定所需的输出使问题易于解决
:test
SETLOCAL
SET "List="
for %%i in (%*) do (
if %fst% equ %%i ( SET "List=!List! %scnd%"
) ELSE (
if %scnd% equ %%i ( SET "List=!List! %fst%"
) ELSE set List=!List! %%i
)
echo "List: " !List!
)
ENDLOCAL
goto :eof
我假设由于缺乏信息,否则可以保证 fst
和 scnd
都保证在输入中只出现一次。
我一直在尝试让以下批处理脚本正常工作,看来我需要请教在 Batch 方面具有更多专业知识的人,因为我不知道为什么它一直无法正常工作。我的目的是交换列表 VAR
的两个元素:
@echo off
rem enable delayed expansion, required for extended usage of environment variables
SETLOCAL EnableDelayedExpansion
SETLOCAL EnableExtensions
set VAR=abcd efgh ijkl mnopq rstvw qwert yxcva rtzewrw yxvys
set fst=qwert
set scnd=rstvw
call :test %VAR%
:test
SETLOCAL
for %%i in (%*) do (
for %%j in (%* %%i) do (
if %scnd% equ %%i (
if %fst% equ %%j (
echo "gotcha before swapping: " "i: " %%i "j: " %%j
set tempor=%%i
set i=%%j
set j=!tempor!
echo "gotcha after swapping: " "i: " !i! "j: " !j!
set List=!List! %%j %%i
)
)
)
set List=!List! %%i
echo "List: " !List!
)
ENDLOCAL
goto :eof
:ende
我试图让列表看起来像这样:
abcd efgh ijkl mnopq qwert rstvw yxcva rtzewrw yxvys
交换 fst(第一个元素)和 scnd(第二个元素)的位置。
输出是这样的:"List: " abcd efgh ijkl mnopq qwert rstvw rstvw qwert yxcva rtzewrw yxvys
,所以我得到了 qwert
和 rstvw
的双重输入,我知道这是因为 set List=!List! %%i
的位置.
至少我知道,交换 正在工作。
但我的问题是:如果我把它放在 else
分支中,就像我通常在任何其他脚本语言中所做的那样,列表将在每个循环中填充 %%i
和 %%j
,所以它变得无用....
您的问题似乎是 %%i
和 %i%
完全是 不同的 变量。您不能为 %%i
赋值 - 只有 for
命令可以。
您似乎在尝试执行插入排序来构建排序的字符串列表。您的代码结构可能是为解决问题而进行的编辑的遗留问题,但正如所发布的那样,例程将通过流程重新输入。此外,由于例程 :test
包含在 setlocal/endlocal 括号中,因此对 list
的更改在 :test
例程之外将不可见。连续使用两个 setlocal
命令会建立两个 嵌套 本地环境。 两个选项可以在一个setlocal
语句中同时指定。请注意,setlocal
不是一个开关 - 它建立了一个本地环境(是的,微软已被要求建立 delayed expansion
等作为单独的 swtich 类型操作,如 echo on/off
)
另请注意,您生成的列表包含前导 space。我用以下替代例程遵循了这个想法:
快速眼动
SET "list2="
for %%i in (%*) do (
REM %%i has each element in turn
SET "startlist= "
SET "endlist= "
IF defined list2 for %%j in (!list2!) do (
IF "%%j" lss "%%i" (
SET "startlist=!startlist!%%j "
) ELSE (
SET "endlist=!endlist!%%j "
)
)
SET "list2=!startlist!%%i!endlist:~0,-1!"
)
ECHO "List2:" %list2%+
(我在末尾添加了一个 +
以显示字符串的结尾 list2
。
是 - 在原始问题中指定所需的输出使问题易于解决
:test
SETLOCAL
SET "List="
for %%i in (%*) do (
if %fst% equ %%i ( SET "List=!List! %scnd%"
) ELSE (
if %scnd% equ %%i ( SET "List=!List! %fst%"
) ELSE set List=!List! %%i
)
echo "List: " !List!
)
ENDLOCAL
goto :eof
我假设由于缺乏信息,否则可以保证 fst
和 scnd
都保证在输入中只出现一次。