Essentially I'm working on a project in command line, and I'm trying to have multiple if statements with multiple conditions to end up with something, in this case, echo displaying something. Here's an example:
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
Now this works fine, displaying what's shown beside echo, and when I add a second one, it also works fine, like so:
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
if %piece%==2 if %haut%==1 (
if %couleur%==1 (
echo haut 2 1 1
) else if %couleur%==2 (
echo haut 2 1 2
))
if %piece%==2 if %haut%==2 (
if %couleur%==1 (
echo haut 2 2 1
) else if %couleur%==2 (
echo haut 2 2 2
))
But once I add a third one which has a different second condition, instead of haut it's pantalon, it suddenly crashes the program instead of giving the answer.
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
if %piece%==2 if %haut%==1 (
if %couleur%==1 (
echo haut 2 1 1
) else if %couleur%==2 (
echo haut 2 1 2
))
if %piece%==2 if %haut%==2 (
if %couleur%==1 (
echo haut 2 2 1
) else if %couleur%==2 (
echo haut 2 2 2
))
if %piece%==3 if %pantalon%==1 (
if %couleur%==1 (
echo pantalon 3 1 1
) else if %couleur%==2 (
echo pantalon 3 1 2
))
if %piece%==3 if %pantalon%==2 (
if %couleur%==1 (
echo pantalon 3 2 1
) else if %couleur%==2 (
echo pantalon 3 2 2
))
I've also tried doing it without the else if, and just having many if statements stacked, but the same problem arises. I'll add the entire code at the end just in case it's needed, but I really don't know what the issue is here and why this is being caused. If someone could help me out, it'd be really appreciated!
Here's the full code:
#echo off
:menu
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle piece vestimentaire voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo -------
echo Hommes
echo -------
echo Haut (1)
echo.
echo Haut (2)
echo.
echo Pantalon (3)
echo.
echo -------
echo Femmes/Tous genres confondus
echo -------
echo Haut (4)
echo.
echo Jupe (5)
echo.
echo Pantalon (6)
echo.
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo.
set /p piece=
if %piece%==1 goto haut
if %piece%==2 goto haut
if %piece%==3 goto pantalon
if %piece%==4 goto haut
if %piece%==5 goto jupe
if %piece%==6 goto pantalon
:haut
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle style d'haut voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Haut (1)
echo.
echo Haut (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set /p haut=
goto couleur
:pantalon
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle style de pantalon voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Pantalon (1)
echo.
echo Pantalon (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set /p pantalon=
goto couleur
:jupe
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle style de jupe voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Jupe (1)
echo.
echo Jupe (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set /p jupe=
goto couleur
:couleur
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle couleurs voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Rouge et noir (1)
echo.
echo Blue et noir (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo.
set /p couleur=
:export
cls
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
if %piece%==2 if %haut%==1 (
if %couleur%==1 (
echo haut 2 1 1
) else if %couleur%==2 (
echo haut 2 1 2
))
if %piece%==2 if %haut%==2 (
if %couleur%==1 (
echo haut 2 2 1
) else if %couleur%==2 (
echo haut 2 2 2
))
if %piece%==3 if %pantalon%==1 (
if %couleur%==1 (
echo pantalon 3 1 1
) else if %couleur%==2 (
echo pantalon 3 1 2
))
if %piece%==3 if %pantalon%==2 (
if %couleur%==1 (
echo pantalon 3 2 1
) else if %couleur%==2 (
echo pantalon 3 2 2
))
if %piece%==4 if %haut%==1 (
if %couleur%==1 (
echo haut 4 1 1
) else if %couleur%==2 (
echo haut 4 1 2
))
if %piece%==4 if %haut%==2 (
if %couleur%==1 (
echo haut 4 2 1
) else if %couleur%==2 (
echo haut 4 2 2
))
if %piece%==5 if %jupe%==1 (
if %couleur%==1 (
echo haut 4 1 1
) else if %couleur%==2 (
echo haut 4 1 2
))
if %piece%==5 if %jupe%==2 (
if %couleur%==1 (
echo haut 4 2 1
) else if %couleur%==2 (
echo haut 4 2 2
))
pause>nul
goto menu
If there's any other information you need I'll be happy to give it!
I would advise that you do not use Set /P to receive expected single digit known input, and instead use the more appropriate and built-in choice.exe utility. This will guarantee that the end user can only provide input from your known list.
As for your if / else, structure, I have removed some unnecessary things, because if many of the options are not 1, they must by default, be 2, so there's no need to ask a second if.
#Echo Off
SetLocal EnableExtensions
:Menu
ClS
Set /A haut=pantalon=jupe=couleur=0
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle piece vestimentaire voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo -------
Echo Hommes
Echo -------
Echo Haut (1)
Echo(
Echo Haut (2)
Echo(
Echo Pantalon (3)
Echo(
Echo -------
Echo Femmes/Tous genres confondus
Echo -------
Echo Haut (4)
Echo(
Echo Jupe (5)
Echo(
Echo Pantalon (6)
Echo(
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 123456
Set "piece=%ERRORLEVEL%"
If %piece%==1 GoTo Haut
If %piece%==2 GoTo Haut
If %piece%==3 GoTo Pantalon
If %piece%==4 GoTo Haut
If %piece%==5 GoTo Jupe
If %piece%==6 GoTo Pantalon
:Haut
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style d'haut voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Haut (1)
Echo(
Echo Haut (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "haut=%ERRORLEVEL%"
GoTo Couleur
:Pantalon
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de pantalon voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Pantalon (1)
Echo(
Echo Pantalon (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "pantalon=%ERRORLEVEL%"
GoTo Couleur
:Jupe
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de jupe voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Jupe (1)
Echo(
Echo Jupe (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "jupe=%ERRORLEVEL%"
GoTo Couleur
:Couleur
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle couleurs voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Rouge et noir (1)
Echo(
Echo Blue et noir (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 12
Set "couleur=%ERRORLEVEL%"
:Export
ClS
If %piece%==1 (
If %haut%==1 (
If %couleur%==1 (
Echo haut 1 1 1
) Else (
Echo haut 1 1 2
)
) Else (
If %couleur%==1 (
Echo haut 1 2 1
) Else (
Echo haut 1 2 2
)
)
)
If %piece%==2 (
If %haut%==1 (
If %couleur%==1 (
Echo haut 2 1 1
) Else (
Echo haut 2 1 2
)
) Else (
If %couleur%==1 (
Echo haut 2 2 1
) Else (
Echo haut 2 2 2
)
)
)
If %piece%==3 (
If %pantalon%==1 (
If %couleur%==1 (
Echo pantalon 3 1 1
) Else (
Echo pantalon 3 1 2
)
) Else (
If %couleur%==1 (
Echo pantalon 3 2 1
) Else (
Echo pantalon 3 2 2
)
)
)
If %piece%==4 (
If %haut%==1 (
If %couleur%==1 (
Echo haut 4 1 1
) Else (
Echo haut 4 1 2
)
) Else (
If %couleur%==1 (
Echo haut 4 2 1
) Else (
Echo haut 4 2 2
)
)
)
If %piece%==5 (
If %jupe%==1 (
If %couleur%==1 (
Echo jupe 5 1 1
) Else (
Echo jupe 5 1 2
)
) Else (
If %couleur%==1 (
Echo jupe 5 2 1
) Else (
Echo jupe 5 2 2
)
)
)
If %piece%==6 (
If %pantalon%==1 (
If %couleur%==1 (
Echo pantalon 6 1 1
) Else (
Echo pantalon 6 1 2
)
) Else (
If %couleur%==1 (
Echo pantalon 6 2 1
) Else (
Echo pantalon 6 2 2
)
)
)
Pause 1>NUL
GoTo Menu
Personally however, I'd perform the if section more like this:
If %piece%==1 If %haut%==1 (
If %couleur%==1 (Echo haut 1 1 1) Else Echo haut 1 1 2
) Else If %couleur%==1 (Echo haut 1 2 1) Else Echo haut 1 2 2
If %piece%==2 If %haut%==1 (
If %couleur%==1 (Echo haut 2 1 1) Else Echo haut 2 1 2
) Else If %couleur%==1 (Echo haut 2 2 1) Else Echo haut 2 2 2
If %piece%==3 If %pantalon%==1 (
If %couleur%==1 (Echo pantalon 3 1 1) Else Echo pantalon 3 1 2
) Else If %couleur%==1 (Echo pantalon 3 2 1) Else Echo pantalon 3 2 2
If %piece%==4 If %haut%==1 (
If %couleur%==1 (Echo haut 4 1 1) Else Echo haut 4 1 2
) Else If %couleur%==1 (Echo haut 4 2 1) Else Echo haut 4 2 2
If %piece%==5 If %jupe%==1 (
If %couleur%==1 (Echo jupe 5 1 1) Else Echo jupe 5 1 2
) Else If %couleur%==1 (Echo jupe 5 2 1) Else Echo jupe 5 2 2
If %piece%==6 If %pantalon%==1 (
If %couleur%==1 (Echo pantalon 6 1 1) Else Echo pantalon 6 1 2
) Else If %couleur%==1 (Echo pantalon 6 2 1) Else Echo pantalon 6 2 2
If all you are doing is really just echoing those values, I'd offer the following modified script, (without changing your screen layout).
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
:Menu
ClS
Set /A haut=pantalon=jupe=couleur=0
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle piece vestimentaire voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo -------
Echo Hommes
Echo -------
Echo Haut (1)
Echo(
Echo Haut (2)
Echo(
Echo Pantalon (3)
Echo(
Echo -------
Echo Femmes/Tous genres confondus
Echo -------
Echo Haut (4)
Echo(
Echo Jupe (5)
Echo(
Echo Pantalon (6)
Echo(
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 123456
Set "piece=%ERRORLEVEL%"
If %piece%==1 GoTo Haut
If %piece%==2 GoTo Haut
If %piece%==3 GoTo Pantalon
If %piece%==4 GoTo Haut
If %piece%==5 GoTo Jupe
If %piece%==6 GoTo Pantalon
:Haut
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style d'haut voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Haut (1)
Echo(
Echo Haut (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "haut=%ERRORLEVEL%"
GoTo Couleur
:Pantalon
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de pantalon voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Pantalon (1)
Echo(
Echo Pantalon (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "pantalon=%ERRORLEVEL%"
GoTo Couleur
:Jupe
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de jupe voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Jupe (1)
Echo(
Echo Jupe (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "jupe=%ERRORLEVEL%"
GoTo Couleur
:Couleur
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle couleurs voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Rouge et noir (1)
Echo(
Echo Blue et noir (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 12
Set "couleur=%ERRORLEVEL%"
:Export
ClS
For %%G In (haut pantalon jupe) Do (SetLocal EnableDelayedExpansion
For %%H In (!%%G!) Do EndLocal & If %%H Gtr 0 Set "var=%%G" & Set "val=%%H")
Echo %var% %piece% %val% %couleur%
Pause 1> NUL
GoTo :Menu
#ECHO OFF
SETLOCAL
:menu
FOR %%b IN (haut pantalon jupe couleur) DO SET /a %%b=0
CALL :accepter piece "piece vestimentaire" 123456 2 "Hommes" "Femmes/Tous genres confondus" 3 "Haut" "Haut" "Pantalon" 3 "Haut" "Jupe" "Pantalon"
GOTO piece%piece%
:haut
:Piece1
:Piece2
:Piece4
CALL :accepter haut "style d'haut" 12 0 2 "Haut" "Haut"
goto couleur
:pantalon
:piece3
:piece6
CALL :accepter pantalon "style de pantalon" 12 0 2 "Pantalon" "Pantalon"
goto couleur
:jupe
:piece5
CALL :accepter jupe "style de jupe" 12 0 2 "Jupe" "Jupe"
goto couleur
:couleur
CALL :accepter couleur "couleurs" 12 0 2 "Rouge et noir" "Blue et noir"
:export
cls
ECHO haut %haut% pantalon %pantalon% jupe %jupe% couleur %couleur%
pause>nul
goto menu
:: receive user input
:: %1 : receiving variable
:: %2 : Menu prompt
:: %3 : options list
:: %4 : number of groups
:: %5 : name of group (repeats %4 times)
:: %then : number of options within group
:: %followedby : Option name
:: %then, %followedby may be repeated
:accepter
cls
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting groupname
For %%b IN (groupname) DO FOR /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
SET "value=%1"
shift
SET "menuprompt=%~1"
shift
SET "options=%1"
SHIFT
SET "groups=%1"
SHIFT
SET /a groupcount=%groups%
SET /a groupindex=0
:getgroupname
IF %groupcount% neq 0 SET /a groupindex+=1&SET "groupname[!groupindex!]=%~1"&SHIFT&IF !groupindex! neq %groupcount% GOTO getgroupname
SET groupname
::
SET /a groupindex=0
SET /a option=0
SET "unusedoptions=%options%"
::
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle %menuprompt% voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:: Display group
:displaygroup
SET /a groupindex+=1
IF DEFINED groupname[%groupindex%] (
echo -------
echo !groupname[%groupindex%]!
echo -------
)
SET numoptionsingroup=%1&SHIFT
:showoption
IF %numoptionsingroup% gtr 0 (
ECHO %~1 (!unusedoptions:~0,1!^)
ECHO.
SET "unusedoptions=!unusedoptions:~1!"
SHIFT
SET /a numoptionsingroup-=1
GOTO showoption
)
IF DEFINED unusedoptions GOTO displaygroup
echo.
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo.
choice /c %options% /M "%menuprompt%"
endlocal&SET %value%=%errorlevel%
GOTO :eof
Related
I have the following code (in batch) to test part of a larger code that isnt working:
#echo off
set /a slotted55=8
set /a place=55
set /a key3=8
set /a key1=0
set /a key2=0
set /a key4=0
set /a key5=0
set /a key6=0
set /a strike=0
if %place%==55 (
if %key1%==%slotted55% (
set key1=V
set slotted55=V
goto 5x5one
) else (
if %key2%==%slotted55% (
set key2=V
set slotted55=V
goto 5x5one
)
) else (
if %key3%==%slotted55% (
set key3=V
set slotted55=V
goto 5x5one
)
) else (
if %key4%==%slotted55% (
set key4=V
set slotted55=V
goto 5x5one
)
) else (
if %key5%==%slotted55% (
set key5=V
set slotted55=V
goto 5x5one
)
) else (
if %key6%==%slotted55% (
set key6=V
set slotted55=V
goto 5x5one
)
) else (
set /a strike=%strike% +1
if %strike%==3 goto gameover
set %slotted55%=X
goto 5x5one
)
)
:gameover
echo gameover
pause
exit
:5x5one
echo good
pause
For some reason, it keeps crashing. I've looked at multiple other questions, but none of them seem to fit this situation. All the variables seem correct, and there are no missing operands, but its not like batch gives you an error message. Can anyone help me?
As I stated in my comment, you do not require any of the else statements, also as your opening if statement does not have an else, you should begin by using the opposite comparison, thus not having everything nested into one set of parentheses.
#Echo Off
SetLocal EnableExtensions
Set "place=55"
Set /A "key3=slotted55=8"
Set /A "key1=key2=key4=key5=key6=strike=0"
If "%place%" NEq "55" GoTo gameover
If "%key1%" == "%slotted55%" (
Set "key1=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key2%" == "%slotted55%" (
Set "key2=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key3%" == "%slotted55%" (
Set "key3=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key4%" == "%slotted55%" (
Set "key4=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key5%" == "%slotted55%" (
Set "key5=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key6%" == "%slotted55%" (
Set "key6=V"
Set "slotted55=V"
GoTo 5x5one
)
Set /A strike += 1
If %strike% Equ 3 GoTo gameover
Set "slotted55=X"
GoTo 5x5one
:gameover
Echo gameover
Pause
Exit /B
:5x5one
Echo good
Pause
Because of where you put your )s, all of your else statements are looking at each other instead of the other if statements that you've written. Right now, your logic looks something like this:
if "%x%"=="5" (
echo X is 5
) else (
echo X is not 5
) else (
echo X is somehow neither 5 nor is it not 5
)
If you combine your else with the next if, your logic makes sense again.
set /a strike=0
if %place%==55 (
if %key1%==%slotted55% (
set key1=V
set slotted55=V
goto 5x5one
) else if %key2%==%slotted55% (
set key2=V
set slotted55=V
goto 5x5one
) else if %key3%==%slotted55% (
set key3=V
set slotted55=V
goto 5x5one
) else if %key4%==%slotted55% (
set key4=V
set slotted55=V
goto 5x5one
) else if %key5%==%slotted55% (
set key5=V
set slotted55=V
goto 5x5one
) else if %key6%==%slotted55% (
set key6=V
set slotted55=V
goto 5x5one
) else (
set /a strike=%strike% +1
if %strike%==3 goto gameover
set %slotted55%=X
goto 5x5one
)
)
You are working with incrementing numbers here, you can just use a for loop and have a single if statement inside a for loop:
#echo off
setlocal enabledelayedexpansion
set /a slotted55=8, place=55, key3=8, key1=0, key2=0, key4=0, key5=0, key6=0, strike=0
if %place% neq %slotted55% goto :gameover
for /L %%i in (1,1,6) do (
if !key%%i! equ %slotted55% (
set "key%%i=V"
set "slotted55=V"
goto :5x5one
)
)
:gameover
set /a strike+=1
if %strike% equ 3 (
echo gameover
pause
exit
)
set "slotted55=X"
:5x5one
echo good
pause
For now, there seems to be something missing here though, you will never reach strike=3 unless you have a goto to return to the loop. So this code will work as yours would have without all the else statements.
When I execute the following Windows batch script on Windows Server 2012:
#echo off
SET v=()
IF 1 == 2 (
echo hi
echo %v:~0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo %v:0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
I get the following output:
1 equals 2
1 does not equal 2
1 does not equal 2
Can anybody tell me why this happens? I don't want to go into the block starting with echo hi even if the value of v is ().
I'm not quite sure what your intention is, but here's how I think your issue can be fixed.
The variable %v% is parsed before the IF command is run, and that contains a problematic closing parenthesis. What happens therefore is that the code reads, echo %v:~0% as echo ( and closes the IF with ) It then parses the next line which is echo 1 equals 2, and prints it as expected.
To prevent that, either escape that parenthesis, when you define that variable:
#echo off
SET "v=(^)"
IF 1 == 2 (
echo hi
echo %v:~0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo %v:0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
Or, better still enable delayed expansion, so that the variable content is not parsed before the command is run, only when it is:
#echo off
SET "v=()"
setlocal enabledelayedexpansion
IF 1 == 2 (
echo hi
echo !v:~0!
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo !v:0!
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
Here I found nice solution to test if variable is a number:
case $string in
''|*[!0-9]*) echo bad ;;
*) echo good ;;
esac
I'm trying to modify it to test if variable is a 1,2,3 or 4-digit natural number (within a range 0-9999), so I added |*[0-9]{5,}* to exclude numbers with more than 5 digits, but the code below prints good for numbers greater then 9999 e.g. 1234567.
case $string in
''|*[!0-9]*|*[0-9]{5,}*) echo bad ;;
*) echo good ;;
esac
I'm using ash from busybox.
You can use numeric testing:
$ s=123
$ (( s>=0 && s<=9999 )) && echo "true" || echo "false"
true
$ s=123456
$ (( s>=0 && s<=9999 )) && echo "true" || echo "false"
false
$ s=-1
$ (( s>=0 && s<=9999 )) && echo "true" || echo "false"
false
You just need to make sure that the string is all digits with optional ± at the start. A non numeric string used in numeric context will evaluate to 0 so you need to test for that.
Which you can use your case statement for:
case $s in
''|*[!0-9]*) echo bad ;;
*) (( s>=0 && s<=9999 )) && echo "true" || echo "false" ;;
esac
Or:
$ [ "$s" -eq "$s" ] 2>/dev/null && (( s>=0 && s<=9999 )) && echo "true" || echo "false"
Works too.
These should work under any POSIX shell.
Not sure if you need this in a case statement, since I would just do:
if { test "$string" -ge 0 && test "$string" -lt 10000; } 2> /dev/null; then
echo good
else
echo bad
fi
If you want to use a case statement in a strictly portable shell, you're probably stuck with:
case $string in
[0-9]|[0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]) echo good;;
*) echo bad;;
esac
case $([[ $num =~ ^[0-9]+$ ]] && echo 0) in
0) echo good ;;
*) echo bad ;;
esac
I have two files, which look like:
File1:
chr id position a0 a1
22 rs4820378:39869209:C:T 39869209 C T
22 22:16050075:A:G 16050075 A G
22 22:16050115:G:A 16050115 G A
22 rs199694733:39913976:C:CT 39913976 C CT
22 rs139408809:39937958:GC:G 39937958 GC G
File2:
SNP CHR BP A1 A2
rs4820378 22 39869209 C T
rs4821900 22 39869719 G A
rs1984662 22 39869997 T G
rs35629588 22 39913976 I2 D
rs139408809 22 39937958 D I2
I would like to find lines where
Fields 1 and 3 from File1 match fields 2 and 3 from File2
and also either
Fields 4 and 5 from File1 are matching fields 4 and 5 from File2
Field 4 from both files have more than 1 character
Field 5 from both files have more than 1 character
Then print out field 2 from File1, and fields 1 and 3 from File2
Code below
#! perl -w
use strict;
use warnings;
my %kglocus;
open( my $loci_in, "<", "File1" ) or die $!;
while ( <$loci_in> ) {
next if m/chr/;
my ( $CHR, $id, $BP, $A1, $A2 ) = split;
my $reg = "${CHR}_$BP";
$kglocus{$reg} = [ $CHR, $id, $BP, $A1, $A2 ];
}
close $loci_in;
my $filename = shift #ARGV;
open( my $input, "<", $filename ) or die $!;
while ( <$input> ) {
next if m/SNP/;
my ( $SNP, $CHR, $BP, $A1, $A2 ) = split;
my $reg = "${CHR}_$BP";
if ( $A1 eq $kglocus{$reg}->[3] and $A2 eq $kglocus{$reg}->[4] ) {
print "$kglocus{$reg}->[1] $SNP $BP\n";
}
elsif ( ( length( $A1 ) > 1 && length( $kglocus{$reg}->[3] ) > 1 ) ||
( length( $A2 ) > 1 && length( $kglocus{$reg}->[4] ) > 1 ) ) {
print "$kglocus{$reg}->[1] $SNP $BP\n";
}
}
close( $input );
I'm getting the error below for all input lines:
Use of uninitialized value in string eq at find_ID.hash.chr22.pl line 23
Use of uninitialized value in length at find_ID.hash.chr22.pl line 27
Can anyone point out the problem?
The problem is that the existence of the hash element $kglocus{$reg} forms the first test, that "Fields 1 and 3 from File1 match fields 2 and 3 from File2". But you are treating it as if that test always passes, and simply using it to access elements of the File1 record
You need something like a next unless $kglocus{$reg} in there to make it work correctly. I would also prefer to see that value pulled out as a separate variable to avoid indexing the hash over and over again
Here's a solution that will work for you
use strict;
use warnings;
use v5.10.1;
use autodie;
my %kglocus;
{
open my $in_fh, '<', 'File1';
while ( <$in_fh> ) {
next if /chr/;
my ( $chr, $id, $bp, $a1, $a2 ) = split;
my $key = "${chr}_$bp";
$kglocus{$key} = [ $chr, $id, $bp, $a1, $a2 ];
}
}
{
my ( $filename ) = #ARGV;
open my $in_fh, '<', $filename;
while ( <$in_fh> ) {
next if /SNP/;
my ( $snp, $chr, $bp, $a1, $a2 ) = split;
my $key = "${chr}_$bp";
next unless my $item = $kglocus{$key};
if ( $a1 eq $item->[3] and $a2 eq $item->[4]
or length $a1 > 1 and length $item->[3] > 1
or length $a2 > 1 and length $item->[4] > 1 ) {
print "$item->[1] $snp $bp\n";
}
}
}
I've wrote a subroutine with some if..else nested
Unfortunately i can't understand why my code are executed before and after the "ELSE" (!!)
I read it for hours, but i don't find any error.. can you help me?
I copied the code (with a lot of echo-debugs) and the output
This is my little code:
setlocal
set debug=echo
%debug% # %~0: %*
for /f "usebackq tokens=1-3 delims=;" %%a in ('"%*"') do (set dir=%%~a& set own=%%~b)
%debug% - dir="!dir!"
%debug% - own="!own!"
%debug% -+ analisi cartella: "!dir!"
if exist "!dir!" (
%debug% x la cartella esiste già, passo oltre
) else (
%debug% - la cartella non esite quindi la creo
mkdir "!dir!" || echo [E] non sono riuscito a creare la cartella&& echo %err3_txt% [dir:!dir!] 1>&2 && exit %err3_id%
)
%debug% -+ analisi proprietario: "!own!"
for /f "usebackq tokens=1,2 delims=\" %%x in ('"!own!\\"') do (set own1=%%~x& set own2=%%~y)
if [!own!] equ [!own:~0,1! ] (
%debug% x il proprietario non è stato specificato quindi non va cambiato, passo oltre
) else (
%debug% - own1: "!own1!"
%debug% - own2: "!own2!"
if [%own2%] equ [] (
%debug% - il proprietario ha un dominio implicito, lo calcolo
set ownn=%own1%
set ownd=%userdomain%
) else (
%debug% - il proprietario ha un dominio esplicitamente indicato
set ownd="input non valido"
if /i [!own1!] equ [L] set ownd=%computername%
if /i [!own1!] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio esplitamente indicato non è riconosciuto: !own1!& echo %err4_txt% [dir:!dir!][own:!own!] 1>&2 & exit %err4_id%)
)
%debug% - la configurazione prevede l'impostazione del seguente proprietario: !ownd!\!ownn!
)
%debug% x done.
this is my output :
# :CSG_check_fs: C:; ;
- dir="C:"
- own=" "
-+ analisi cartella: "C:"
x la cartella esiste giÓ, passo oltre
-+ analisi proprietario: " "
x il proprietario non Þ stato specificato quindi non va cambiato, passo oltre
- own1: " "
- own2: ""
- il proprietario ha un dominio implicito, lo calcolo
- la configurazione prevede l'impostazione del seguente proprietario: CSG\
x done.
in particular, let us appropriate commands are executed BEFORE and AFTER the else clause!!!
why??? this thing is incredible!! or am i too tired?
It is certainly very odd. CMD seems to be having a real problem with this very complex statement (and so do I...) :
if [!own!] equ [!own:~0,1! ] (
%debug% x il proprietario non è stato specificato quindi non va cambiato, passo oltre
) else (
%debug% - own1: "!own1!"
%debug% - own2: "!own2!"
if [%own2%] equ [] (
%debug% - il proprietario ha un dominio implicito, lo calcolo
set ownn=%own1%
set ownd=%userdomain%
) else (
%debug% - il proprietario ha un dominio esplicitamente indicato
set ownd="input non valido"
if /i [!own1!] equ [L] set ownd=%computername%
if /i [!own1!] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio esplitamente indicato non è riconosciuto: !own1!& echo %err4_txt% [dir:!dir!][own:!own!] 1>&2 & exit %err4_id%)
)
%debug% - la configurazione prevede l'impostazione del seguente proprietario: !ownd!\!ownn!
)
Looking at
if [!own!] equ [!own:~0,1! ] (
You may think that this should be evaluated, with OWN set to a single space, as
if [ ] equ [ ] (
Which should generate a syntax error because the third token in the command is ] and that's not a valid comparison-operator. The !var! confuses matters because it can't be evaluated until EXECUTION TIME - and by then, the parser has finished its work.
The correct form is
if "%own%" equ "%own:~0,1% " (
because the parser can then substitute the CURRENT (ie. PARSE-TIME) value of own and the syntax is "quoted string" operator "another quoted string"
I'm sure that this change would solve the major part of the problem.
Similarly,
if [%own2%] equ [] (
should be
if "%own2%" equ "" (
or even (my preference)
if not defined own2
and the same goes for the other IF [..] equ [...] constructs.
Finally, in the sequence
set ownd="input non valido"
if /i [!own1!] equ [L] set ownd=%computername%
if /i [!own1!] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio ...
there's a small problem (other than the if..[...
ownd may be SET within the code, but the %ownd% in the last of these lines will have the PARSE-TIME value of ownd substituted, so it's unlikely to contain the target string. Here's where you NEED !var! because the value of var is being changed by the code and you want the changed value, not the value as it stood when the statement was parsed.
HTH
Imo this might be not perfect, but please keep in mind, this is no de-bugging service here & I'm not your father, Luke.
# echo off&setlocal
for /f "usebackq tokens=1-3 delims=;" %%a in ("%*") do (set dir=%%~a& set own=%%~b)
if not exist "%dir%" mkdir "%dir%" || echo [E] non sono riuscito a creare la cartella&& echo %err3_txt% [dir:%dir%]&& exit %err3_id%
for /f "usebackq tokens=1,2 delims=\" %%x in ("%own%\\") do (set own1=%%~x& set own2=%%~y)
if not [%own%] equ [%own:~0,1%] (
if [%own2%] equ [] (
set ownn=%own1%
set ownd=%userdomain%
) else (
set "ownd=input non valido"
if /i [%own1%] equ [L] set ownd=%computername%
if /i [%own1%] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio esplitamente indicato non è riconosciuto: %own1%& echo %err4_txt% [dir:%dir%][own:%own%]& exit %err4_id%)
)
)