I've been trying to get following batch script working, looks like I need to ask someone with more expertise in Batch, as I don't have any clue, why it keeps not working. My intention is to get two elements of the list VAR
gets swapped:
@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
I am trying to get the List to look like this:
abcd efgh ijkl mnopq qwert rstvw yxcva rtzewrw yxvys
where the fst (for first element) and scnd (second element) get swapped.
The output is like this: "List: " abcd efgh ijkl mnopq qwert rstvw rstvw qwert yxcva rtzewrw yxvys
, so I get double entry of qwert
and rstvw
, and I know it is because of the position of set List=!List! %%i
.
At least I know, the swapping is working.
But my problem is: if I put this in the else
branch, as I would normally do in any other script language, the List will be filled with %%i
and %%j
in every loop, so it becomes useless....
Your problem appears to be that %%i
and %i%
are entirely different variables. You cannot assign values to %%i
- only the for
command can.
You appear to be attempting to perform an insertion-sort to build a sorted list of strings. Your code-structure may be a legacy of edits to present the problem, but as posted, the routine will be re-entered by flow-through. Also, since the routine :test
is enclosed in a setlocal/endlocal bracket, changes to list
will not be visible outside of the :test
routine. And having two setlocal
commands in succession establishes two nested local environments. Both of the options can be specified simultaneously in one setlocal
statement. Note that setlocal
is not a switch - it establishes a local environment (and yes, microsoft has been asked to establish delayed expansion
and the like as separate swtich-type operations like echo on/off
)
Also note that your generated list contains a leading space. I've followed that idea with the following substitute routine:
REM
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%+
(I've added a +
to the end to show the end of the string list2
.
Yes - specifying the required output in the original question makes the problem easy to solve
: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
I'm assuming for lack of information otherwise that it's guaranteed that fst
and scnd
are both guaranteed to appear exactly once in the input.