Mam dwa przykłady bardzo prostych plików wsadowych:
Przypisywanie wartości do zmiennej:
@echo off
set FOO=1
echo FOO: %FOO%
pause
echo on
Co zgodnie z oczekiwaniami skutkuje:
FOO: 1
Press any key to continue . . .
Jeśli jednak umieszczę te same dwie linie w bloku IF NOT DEFINED:
@echo off
IF NOT DEFINED BAR (
set FOO=1
echo FOO: %FOO%
)
pause
echo on
Ten nieoczekiwanie skutkuje:
FOO:
Press any key to continue . . .
To nie powinno mieć nic wspólnego z IF, oczywiście blok jest wykonywany. Jeśli zdefiniuję BAR powyżej if, wyświetlony zostanie tylko tekst z polecenia PAUZA, zgodnie z oczekiwaniami.
Co daje?
Dalsze pytanie: Czy jest jakiś sposób, aby włączyć opóźnioną ekspansję bez setlocal?
Gdybym miał wywołać ten prosty przykładowy plik wsadowy z innego, przykład ustawia FOO, ale tylko LOKALNIE.
Na przykład:
testcaller.bat
@call test.bat
@echo FOO: %FOO%
@pause
test.bat
@setlocal EnableDelayedExpansion
@IF NOT DEFINED BAR (
@set FOO=1
@echo FOO: !FOO!
)
Wyświetla to:
FOO: 1
FOO:
Press any key to continue . . .
W tym przypadku wydaje się, że muszę włączyć opóźnione rozszerzenie w CALLER, co może być kłopotliwe.
źródło
!
, użyj^^^!
(dwa razy ucieknij). W przeciwnym razie funkcja „opóźnionego rozszerzenia” zje to.To samo zachowanie występuje również, gdy polecenia znajdują się w jednym wierszu (
&
jest to separator poleceń):Wyjaśnienie Joeya jest moim ulubionym. Należy jednak pamiętać, że
enabledelayedexpansion
to nie działa w systemie Windows NT 4.0 (i nie jestem pewien co do systemu Windows 2000).Jeśli chodzi o twoje pytanie uzupełniające, nie, nie można tego zrobić
EnableDelayedExpansion
bezsetlocal
. Jednak oryginalne zachowanie, które było przeciwko tobie, może zostać wykorzystane do obejścia tego drugiego problemu: sztuczka polegaendlocal
na tym, że w tym samym wierszu, w którym ponownie ustawiasz wartości zmiennych, których potrzebujesz.Oto twoje
test.bat
zmodyfikowane:Ale oto inne obejście tego problemu: użyj procedury w tym samym pliku zamiast wbudowanego bloku lub pliku zewnętrznego.
źródło
Jeśli to nie działa w ten sposób, prawdopodobnie opóźnione jest rozszerzanie zmiennych środowiskowych. Możesz to wyłączyć za pomocą
cmd /V:OFF
lub użyć wykrzykników, jeśli:źródło
Dzieje się tak, ponieważ twoja linia z
FOR
poleceniem ocenia tylko raz. Potrzebujesz sposobu, aby to ponownie ocenić. Można symulować opóźnione rozszerzenie za pomocąCALL
polecenia:źródło
Warto zauważyć, że działa, jeśli jest to pojedyncze polecenie w tej samej linii.
na przykład
ustawi się
FOO
na 1. Możesz wtedy wykonać kolejne sprawdzenie, takie jak:Hej, nigdy nie mówiłem, że to było ładne. Ale jeśli nie chcesz zadzierać z firmą setlocal lub firmą z opóźnioną ekspansją, jest to szybkie obejście.
źródło
Czasami, tak jak w moim przypadku, gdy musisz być kompatybilny ze starszymi systemami, takimi jak stare serwery NT4, w których opóźnione rozszerzenie nie działa lub z jakiegoś powodu nie działa, możesz potrzebować alternatywnego rozwiązania.
W przypadku korzystania z Opóźnionego rozszerzenia zaleca się również, aby przynajmniej zameldować partię:
Jeśli chcesz tylko bardziej czytelne i proste podejście, oto alternatywne rozwiązania:
który działa w ten sposób:
i jeszcze jedno czyste rozwiązanie cmd:
to działa tak:
i to jest pełne, JEŚLI TO INNE rozwiązanie składniowe:
to działa tak:
źródło