2016-01-18 35 views
6

i @echo off wydają się nie mieć żadnego wpływu, gdy są wykonywane w bloku o rozmiarze w nawiasach kwadratowych if w pliku wsadowym. Oto proste demo:Dlaczego funkcja @ECHO ON/OFF nie działa w bloku pliku wsadowego IF?

@echo off 
echo Test #1 
if 1 == 1 (
    @echo on 
    echo Test #2 
    @echo off 
    echo Test #3 
) 
@echo on 
echo Test #4 

Wyjście z systemem wyżej w linii poleceń jest:

testowy nr 1
testowy nr 2
test nr 3
C: \ mybatchfilelocation> test echa # 4
Test # 4

Czy ktoś mógłby to wyjaśnić i/lub r zaproponować obejście? (oczekiwać, że prawdopodobnie może być ustalona przez obfitym wykorzystaniem goto i etykiet, ale wolałby, aby kontynuować korzystanie nawias jeśli bloki jeśli to możliwe ...)

+0

Myślę, że dzieje się tak dlatego, że obecny stan "echo on/off" wpływa tylko na całą linię lub blok; jeśli chcesz kontrolować go dla każdego polecenia osobno, ustaw 'echo on' i poprzedzaj każde polecenie, które chcesz ukryć za pomocą' @ '; – aschipfl

+0

Dzięki, ale niestety wygląda na to, że 'echo on' nie będzie wyświetlać poleceń w nawiasach (zobacz moją nowo dodaną odpowiedź poniżej). –

+0

Nie rozumiem, oba "echo" w twojej odpowiedzi _jest_ 'echo'ed; wstaw '@' przed jednym z 'echo's, aby go ukryć; wstaw '@' przed '(' aby ukryć wszystko po 'if' ... – aschipfl

Odpowiedz

5

Jak odkryli, zmieniony stan ECHO nie jest rozpoznawany przez parser, aż osiągnie oświadczenie, że jest po bloku kodu, który zawiera ECHO ON/OFF.

Ale istnieje jeden wyjątek - polecenia po FOR ...Zrób zmianę stanu w tym samym bloku :-)

Pamiętaj, że potrzebujesz tylko @, aby wyłączyć wyjście polecenia, gdy ECHO jest aktualnie WŁĄCZONE. Jeśli jest WYŁĄCZONY, nie ma potrzeby, aby @ECHO ON. A jeśli go włączysz i wyłączysz w tym samym bloku kodu, to też go tam nie potrzebujesz.

Oto demo że Echos linie nawet testowe:

@echo off 
echo Test #1 
(
    echo on 
    for %%. in (.) do echo Test #2 
    echo off 
    echo Test #3 
    echo on 
    for %%. in (.) do echo Test #4 
    echo off 
    echo Test #5 
) 
echo on 
echo Test #6 
@echo off 
echo Test #7 

- WYJŚCIE -

Test #1 

C:\test>echo Test #2 
Test #2 
Test #3 

C:\test>echo Test #4 
Test #4 
Test #5 

C:\test>echo Test #6 
Test #6 
Test #7 

Może się okazać, że wygodnie zadeklarować prosty echo_on "makro". Następujące daje dokładnie to samo wyjście:

@echo off 
setlocal 

set "echo_on=echo on&for %%. in (.) do" 

echo Test #1 
(
    %echo_on% echo Test #2 
    echo off 
    echo Test #3 
    %echo_on% echo Test #4 
    echo off 
    echo Test #5 
) 
echo on 
echo Test #6 
@echo off 
echo Test #7 
+0

Świetna odpowiedź i dobra sztuczka! Tylko jedno, czy wiesz coś na temat wewnętrznych elementów - czyli dlaczego "FOR" ... "DO" jest wyjątkiem od reguły? –

+1

@SteveChambers - Przypuszczam, że ponieważ FOR jest jedynym poleceniem, które ECHO jest wielokrotnie. Pierwsze ECHO dla całego oświadczenia FOR jest wyłączone. Ale polecenia DO są następnie ECHOed raz dla każdej iteracji. Zobacz http://stackoverflow.com/a/4095133/1012053, aby uzyskać więcej informacji. – dbenham

1

Właśnie dowiedziałem się, co jest przyczyną tego, przekręcając echo na przed blok if.

@echo on 
if 1 == 1 (
    echo Test #1 
    echo Test #2 
) 

ten wyjścia:

C: \ mybatchfilelocation> if 1 == 1 (
echa testowy 1
echa test # 2
)
test 1 test
# 2

Tak więc wyrażenie to ech oed to cały blok if, a nie każde wyrażenie w nim. This answer wyjaśnia to dalej i this answer podaje obejście - niestety nie to, co chciałem usłyszeć, ale wygląda na to, że wiele z nich może być jedynym możliwym do zastosowania rozwiązaniem.

+1

Z mojego doświadczenia wynika, że ​​tworzenie "bloku" z nawiasami nie jest tak naprawdę robieniem czegoś takiego w dowolnym języku programowania, ponieważ cała rzecz zostaje sparsowana/zmieniona na raz, zanim kiedykolwiek zostanie uruchomiona. robisz, spodziewałbym się, że zadziała tak jak ty, ale nie mogę powiedzieć, że jestem zaskoczony dziwnymi zachowaniami z cmd/if. – mojo

+1

To zachowanie jest takie samo, że wymagało opóźnionego rozszerzenia, aby uzyskać dostęp do zmiennych zmodyfikowanych w bloku: jeśli 'echo on' _przed tym blokiem, wszystkie linie w bloku zostaną pokazane, nawet jeśli umieścimy w nim' echo off' i imadło versa: jeśli 'echo off' przed blokiem, wszystkie linie nie będą wyświetlane, nawet z' echo on' wewnątrz bloku. Ostatni stan echa jest używany w pierwszym wierszu po bloku. – Aacini

2

Można zrobić coś takiego osiągnąć wynik chcesz:

@echo off 
set "ExecuteCmd=echo Test #2" 
echo Test #1 
if 1 == 1 (
    echo %ExecuteCmd% 
    %ExecuteCmd% 
    echo Test #3 
) 
@echo on 
echo Test #4 
+0

Nie jest to zła próba alternatywna, ale ponieważ istnieje wiele możliwych poleceń, które mogą być wykonane w bloku 'if' wygląda jak' goto's, a etykiety będą bardziej praktyczne. –

1

Jak o wprowadzenie echo poleceń sterujących wewnątrz podprogramu?

@echo off 
echo Test #1 
if 1 == 1 (
    CALL :DO_ECHO_ON 
    echo Test #3 
) 
@echo on 
echo Test #4 

@EXIT /B 

:DO_ECHO_ON 
@ECHO ON 
echo Test #2 
@ECHO OFF 
@EXIT /B 

Daje to wynik, którego oczekuję od Twojego opisu.

Test #1 

C:\secret>echo Test #2 
Test #2 
Test #3 

C:\secret>echo Test #4 
Test #4 

Na podstawie jednego z twoich komentarzy, przypuszczam, że chcesz móc włączyć echo dla dowolnych poleceń. Ta zmodyfikowana wersja to robi.

@echo off 
echo Test #1 
if 1 == 1 (
    CALL :DO_ECHO_ON_CMD echo Test #2 
    echo Test #3 
    CALL :DO_ECHO_ON_CMD dir /b "C:\Program Files" 
    echo Test #3.1 
    CALL :DO_ECHO_ON_CMD attrib c:\Windows 
) 
@echo on 
echo Test #4 

EXIT /B 

:DO_ECHO_ON_CMD 
@ECHO ON 
%* 
@ECHO OFF 
@EXIT /B 0