Strange behavior inside IF block in a batch file - batch-file

I have this batch file here and it doesn't run well. It says "( was unexpected at this time". Do you know why?
#ECHO OFF
SET A[0]=HOLA
SET A[1]=HELLO
SET I=0
:LOOP
IF DEFINED A[%I%] (
ECHO %I%
CALL SET B=%%A[%I%]%%
CALL ECHO %%B%%
IF %B% == HOLA (
ECHO ES
) ELSE (
ECHO EN
)
PAUSE
SET /A I+=1
GOTO :LOOP )
My expected output should be:
0
HOLA
ES
1
HELLO
EN
I don't understand why inside IF everything works different. Thanks in advance.

#ECHO OFF
SETLOCAL
SET "A[0]=HOLA"
SET "A[1]=HELLO"
SET /a I=0
:LOOP
IF DEFINED A[%I%] (
ECHO %I%
CALL SET "B=%%A[%I%]%%"
CALL ECHO %%B%%
FOR /f "delims==" %%b IN ('set B') DO IF /i "%%b"=="B" (IF "%%c"=="HOLA" (SET "Same=Y") ELSE SET "Same=")
IF DEFINED Same (
ECHO ES
) ELSE (
ECHO EN
)
rem PAUSE
SET /A I+=1
GOTO LOOP
)
GOTO :EOF
Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign a terminal \, Space or " - build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.
Your set syntax sets the value of the variable to the rest of the line.
Hence, the line including the label loop would be assigned to i.
if %B%... substitutes the value of B at the time the block was parsed. AT that time, B was not defined, so nothing is substituted, so the result is if == HOLA (... and cmd does not expect ( at this point and objects.
The complex line I've shown performs a set command on all variables that start b and assigns %%b to the variable name, %%c to its current value. There may be many variables that start B, so we need to select exactly B, and if B's value in %%c is HOLA then set Same, otherwise set Same to nothing, which means that Same will either be assigned, or not assigned respectively.
if defined operates on the current value of the variable, so same can be used safely to do the if processing.
BUT The clean way to do this is by using delayedexpansion.
Stephan's DELAYEDEXPANSION link

Related

Sum in batch script

How can I make the sum of the imputed numbers given by the user from the keyboard ? I tried a for loop but is endless. I cannot figure out a break statement.
::#ECHO OFF
setlocal EnableDelayedExpansion
set /p X=
SET /A suma=0
:Loop
FOR %%G IN (%X%) DO (
IF %%G GTR 0 (
SET /A suma=%suma%+%%G
)
)
SHIFT
GOTO Loop
:completed
echo %suma%
What i want to do is to make the program more user friendyl like echo somthing for the user to know it is supposed to write somthing. I know the correct code for this question, but the numbers are given as parameters in the command (syntax: script.bat parameter1 parameter2 parameter3).
::#ECHO OFF
SET /A suma=0
:Loop
IF "%1"=="" GOTO completed
FOR %%F IN (%1) DO (
IF %1 GTR 0 (
SET /A suma=%suma%+%1
)
)
SHIFT
GOTO Loop
:completed
echo %suma%
Please give me any idea for the breaking statement in the first example or how can I modify the code to take the numbers from the users imput variable and not as paramaters.
Thank you.
SET /A suma=0
set "X=%*"
if not defined X set /p "X=No parameters detected "
if not defined X ECHO No user-input detected&goto completed
FOR %%G IN (%X%) DO (
IF %%G GTR 0 (
SET /A suma=suma+%%G
)
)
:completed
echo %suma%
%* means the command-line tail. If no tail, then ask user for input. If still no data, issue message and show result.
shift moves the command line tail one position, so %2 becomes %1, etc. You haven't provided a test to exit the routine - and the command-line tail is presumably empty, so you are shifting it (which does nothing) and looping.
The for...%%G.. processes the entire list %X%, so there's no point in the shift/loop - the data has already been processed.

Rename value in column via batch

I have a tab delimited txt file and I am trying to find the value 0 in the last column in every line then rename that value from 0 to K.This is the code I have come up with so far but I can't get the values to change. What am I doing wrong here?
ECHO ON
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=E:\psexport"
SET "destdir=E:\psexport"
SET "filename1=%sourcedir%\nk3.txt"
SET "outfile=%destdir%\nk4.txt"
(
FOR /f * IN ("%filename1%") DO (
SET "line=*"
SET "line=!line:0=K"
ECHO !line!
)
)>"%outfile%"
GOTO :EOF
`
You are using bang where I would expect to see percentage. Also, I'm not sure about that second set statement.
See my code example below. In the echo command I am calling line, with the variable substitution of replace 0 with K. It's wrapped in percentages because that whole expression is the variable we want to echo.
ECHO ON
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=E:\psexport"
SET "destdir=E:\psexport"
SET "filename1=%sourcedir%\nk3.txt"
SET "outfile=%destdir%\nk4.txt"
(
FOR /f * IN ("%filename1%") DO (
SET "line=*"
ECHO %line:0=K%
)
)>"%outfile%"
GOTO :EOF
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=E:\psexport"
SET "destdir=E:\psexport"
SET "filename1=%sourcedir%\nk3.txt"
SET "outfile=%destdir%\nk4.txt"
(
FOR /f "usebackq delims=" %%a IN ("%filename1%") DO (
SET "line=%%a"
IF "!line:~-2!"==" 0" (
ECHO !line:~0,-2! K
) ELSE (
ECHO %%a
)
)
)>"%outfile%"
GOTO :EOF
The for syntax requires a metavariable - I've used %%a - which is alphabetical and case-sensitive.
The modifier usebackq is used because the name of the file being read is quoted.
delims= means no delimiters, so the entire file line is delivered to %%a.
To use substringing, we need to transfer the value to a standard environment variable, then test that the last two characters of the line read are 0 so that 10 does not get modified. If the test is true, echo the line from the beginning (character 0) through to the end - 2 characters and append K, otherwise, regurgitate the original line.
The set syntax you were using replaces every 0 with K.

Why the % variable is not working as ! variable in my batch file?

I am using array in my for loop and trying to assign the value to a variable when each time loop process the array value. but when I am assigning the value to my variable, then the result is not as expected.
Here is what I am trying to do:
#echo off
setlocal enabledelayedexpansion
SET var[0]=a
SET var[1]=b
SET var[2]=c
SET var[3]=d
for %%a in (0,1,2,3) do (
SET name=%var[%%a]%
ECHO %name%
)
but the result is showing the last value of array which is 'd'. I don't want to use ECHO !name!. And expecting the output as below with %
a
b
c
d
Normally it would shown ECHO is off. because %name% wasn't declared before. Let's say that you set the default value to null for %name%, then the output would be null instead of a, b, c and d. That's because %name% was declared outside the loop.
What is going on here? The echo %name% inside the code block will get the variable %name% first before run it, and therefore your code inside code block after parsed would be:
(
set name=
rem "%var[%" = "" and "%a]%" also = ""
echo
rem %name% wasn't here, because it's parsed before you run it.
)
The ! symbol is the alternative variable pre/suffix, and only works if you use
setlocal EnableDelayedExpansion
Variable that's use ! will only get parsed when the statement is actually running instead of parsing:
(
set name=!var[%%a]!
echo !name!
)
This time, the code block would ignore the ! symbol and only looking for % symbol, and because the for loop, %%a will replace by a number:
(
set name=!var[0]!
echo !name!
)
(
set name=!var[1]!
echo !name!
)
(
set name=!var[2]!
echo !name!
)
(
set name=!var[3]!
echo !name!
)
Next time, if you want to change variable and use it, you might have to use ! instead of % otherwise you'll get repeated result. And if you want to echo the ! symbol, you can just escape it:
echo escaped "^!" symbol^!

Write function's returning value to specified variable in Batch

I have to write a function that returns length of the specified variable to the second one. Actually, I don't know how to do it. I had several ideas like set %~2=%len% or set len=call :parse_to_tokens %input%, but they didn't work.
:length
set string=%~1
set len=0
:loop
if defined string (
set string=%string:~1%
set /a len+=1
goto loop
)
:: The return statement or something.
exit /b 0
set /p input=""
call :parse_to_tokens %input% %len%
echo %len%
:: Prints input length.

Batch file doesn't work, how can I to fix it?

I want to write a game using a batch script, but there is an error and I don't know what to do.
#echo on
goto log
:inicio
set "esquerda=caverna"
set "esquerda2=6"
set /p "run=Digite a acao: "
if %run%==help (
goto help) else (
goto comands)
:carvena
echo oi>"%userprofile%\desktop\oi.txt"
pause>nul
:comands
echo %run% >"%tmp%\reino_de_merlock\personagem\comands.txt"
cd "%tmp%\reino_de_merlock\personagem"
type comands.txt | find /i "andar_esquerda" && echo andar>andar_esquerda.txt
if exist andar_esquerda.txt (
set "andar=esquerda1"
del /q andar_esquerda.txt
goto andar1)
:log
for /f %%a in ('type "%tmp%\reino_de_merlock\personagem\agilidade.txt"') do (
set "agilidade=%%a" & goto inicio)
:andar1
if "%andar%" == "esquerda1" (
set /a andar = agilidade - esquerda2
if %andar% LEQ 0 (
goto %esquerda%)) 1>nul 2>nul
pause>nul
The error is in set /a andar = agilidade - esquerda2, the variable becomes esquerda1 and the right it's -2, what is the error?
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed.
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
In your case,
if %andar% LEQ 0 (
goto %esquerda%)
is contained within the block that starts
if "%andar%" == "esquerda1" (
and consequently uses the values of andar and esquerda1 as they were when the if "%andar%" == "esquerda1" was reached, not on the new value of andar calculated within the loop.
Look for many SO entries on 'delayed expansion'

Resources