Warum funktioniert der choice Befehl für batch nicht wie er soll?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

kleine Unterrichtsstunde gefällig?🧐🤫

...oder geh zum Ende meiner Antwort, da steht was Wichtiges...

Batch ist im eine uralte äußerlich sehr simpel gestrickte Stapelverarbeitung.

ein Stapel von Kommandos schön zeilenweise

wird abgearbeitet. Nicht verwunderlich das die Auswertung einer frisch gesetzten Variable erst ab der nächsten Zeile erwartet wird.

set "Var=blubb"
echo %var%

Das klappt wie erwartet, die Variable wird in der nächsten Zeile abgerufen.

Jetzt kommt der Kasus Knacksus : Alle Befehle innerhalb eine Klammerblocks werden vom Kommandointerpreter als eine Zusammenhängende Zeile ausgewertet.

(
    set "Var=blubb"
    echo abgerufen innerhal des  gleichen Klammeblocks: %var%
)
echo abgerufen ausserhalb Klammeblocks: %var%

Da die variable vor dem setzen in der Klammer keinen Wert hatte ist nichts zum abrufen da. Es kommt noch schlimmer. Wenn die Variable vor dem setzen bereits eien anderen Wert als den in den Klammern gesetzten Wert hatte kann auch das Ergebnis eines Vergleichs völlig falsch sein:

set "Var=0"
if "%Var%"=="0" (
  set "Var=1"
  if "%Var%"=="1" goto :label1
)
echo da ging was schief...
pause
exit /b

:label1
echo hier sollte ich ankommen
pause

Klammerblöcke haben noch andere Tücken, das ist jedoch hier irrelevent. Fast Dein gesamtes Script ist Quasi eine Zeile... darin sind alle gesetzten Variablen tot. Hätten aber nach dem Sprung zu :top den in vorherigen Runde eingegebenen Wert. (lass mal schön das Echo off am Anfang weg, dann siehst Du was die aufgelösten Variablen enthalten!

Wie kommst Du am billigsten aus der Misere heraus? ...in diesem simplen Fall den Klammeblock loswerden.

demo1.cmd

:top
  rem negative  Logik... überspringe das Menü wenn %$ecbId% nicht Leer  ist.
if "%$ecbId%" neq "" goto :fragNicht
    echo Enter 1 for ...
    echo Enter 2 for ...
    set /p choice="Type input: "
    if "%choice%"=="1" (
        echo 1
        timeout 3
    )
    if "%choice%"=="2" (
        echo 2
        timeout 3
    )
:fragNicht
goto top

Das läuft wie es soll.

Dein Menü ist Mist, da der Nutzer auch etwas völlig blödes eingaben kann. Erlaube einem Nutzer nur Eingaben auf welche Dein Programm möglichst einfach reagieren kann. der Choice-Befehl reagiert nur auf die vorgegebenen Zahlen/Buchstaben.

echtesChoiceMenu.cmd

@echo off
chcp 65001 >nul


echo [1]Irgendwas   [2]Was anderes
echo [X] Programm beenden
:ask
choice /c 12x /m "Wähle:"
if %errorlevel% equ 1 (
    echo Irgendwas gewählt
    timeout 3 >nul
    goto :ask
)
if %errorlevel% equ 2 (
    echo Was anderes gewählt
    timeout 3 >nul
    goto :ask
)
 rem da nur noch  die 3.Option übrig ist und  die anderen Beiden wegspringen Du Dir einen weiteren Vergleich sparen
echo winke...Winke...
timeout 5 >nul

Sollte es unumgänglich sein verschachtelte Variablenzugriffe innerhalb eines Klammerblocks auszuführen, ist di einfachste Option die verzögerte Variablenexpansion:

demo3.cmd

@echo off
chcp 65001 >nul
setlocal enableDelayedExpansion


echo [1]Irgendwas   [2]Was anderes
echo [X] Programm beenden
:ask
rem !!!!Achtung innerhalb  eines Klammerblocks sind  keine  Sprünge  möglich!!!!!
rem ein :label  kann eine Batch crashen . ein goto zu einem Label  außerhalb  der Klmmern  ist  jedoch möglich
if irgendwas==irgendwas (
    choice /c 12x /m "Wähle:"
    if !errorlevel! equ 1 (
        echo Irgendwas gewählt
        timeout 3 >nul
        goto :ask
    )
    if !errorlevel! equ 2 (
        echo Was anderes gewählt
        timeout 3 >nul
        goto :ask
    )
    echo winke...Winke...
    timeout 5 >nul
    exit /b
)


echo irgendwelches zeug wen irgendwas nicht  irgendwas ist
pause  

... setlocal enableDelayedExpansion ist aber kein Allheilmittel. Das bringt neue Probleme mit sich....

Wenn Du den Krampf übersprungen hast...

Batch ein Flickenteppich von Regeln, Ausnahmen von Regeln, Ausnahmen von den Ausnahmen, usw. Viele Anfänger fallen auf die simple Basissyntax herein. Wenn sie auf den Geschmack am Programmieren gekommen sind und etwas mehr als Spagetticode produzieren wollen, schlägt das Monster zu.

...und man muss schon echt viel Langeweile haben um sich Batch in all seinen Fasetten anzutun und Batch kann echt fies werden: https://www.gutefrage.net/frage/csv-daten-in-batch-anzeigen#answer-451313130

Vergiss Batch... Powershell ist viel angenehmer.

Hui. Also:

  1. Das ist NICHT der Choice Befehl. DAS und DAS ist der Choice Befehl.
  2. Du fragst nach einer Eingabe des Nutzers um eine Variable festzulegen. Mit dem Choice Befehl fragst du nach einer Eingabe eines einzelnen Buchstabens/einer einzigen Zahl, und untersuchst dann den Errorlevel. Lies dir dazu mal dies durch.
  3. Bei  "if "%choice%"=="1" (" Z.7 musst du die " Dinger bei den = Zeichen und bei der 1 weglassen. Gleiches gilt für das 2.

PS: Mit "cls" kannst du den Bildschirm löschen, damit du nicht immer mehr Zeilen hast sondern sich immer wieder neu aufbauende "Seiten".

Viel Glück!

Woher ich das weiß:eigene Erfahrung
Elwag12  16.10.2022, 20:21

Du musst die Gänsefüßchen übrigens ebenso bei "Choice" entfernen, und auch bei "Type Input"!

0
Elwag12  16.10.2022, 20:22

Wenn du den 3. Punkt berücksichtigst sollte es schon funktionieren. Alternativ kannst du natürlich auch den richtigen Choice Befehl verwenden. :)

0