2017-03-22 71 views
3

一個動態的標籤。如果我要打電話:從bar.bat中foo foo.bat我做的:如何調用不同的.bat文件

::foo.bat 
echo.wont be executed 
exit /b 1 
:foo 
echo foo from foo.bat 
exit /b 0 

::bar.bat 
call :foo 
exit /b %errorlevel% 
:foo 
foo.bat 
echo.will also not be executed 

但是,如果我不知道標籤的名稱,但把它作爲一個參數我堅持

::bar.bat 
:: calling a dynamic label is no problem 
call :%~1 
exit /b %errorlevel% 
::don't know how to "catch-all" or set context of "current-label" 
:%~1 
foo.bat 
+1

在解析變量或參數引用之前,解析器會逐字地搜索標籤,因此您不能在標籤中使用這樣的標籤...... – aschipfl

+0

會出現'If Not'%〜1「==」「Call:%〜1' help? – Compo

+1

恐怕我不理解你的擔憂。要調用動態標籤,只需使用'call:%〜1'形式。但是,應該很明顯,第一個批處理文件中必須存在這樣的標籤! (也在第二個)。如果你想調用第二個批處理文件_always_(不管該參數),只需要將該參數傳遞給第二個批處理文件:'call foo.bat%1'並使用'goto%〜'開始'foo.bat' 1'(除非你想讓事情更復雜)。 – Aacini

回答

1

標籤是由解析器搜索字面上解決環境變量或參數的引用之前,所以你不能在標籤中使用此類。
然而,在此我想提供一種方法,它允許使用動態標籤,雖然我不明白什麼是這樣做的目的,所以這是比較厚道的學術回答...

批處理文件分析器cmd不會緩存批處理文件,它會逐行讀取並執行它,或者正確說出,它會逐個讀取並執行每個命令行/塊。所以我們可以利用它並讓批處理文件在執行過程中自行修改,因爲修改的部分不在當前執行的代碼部分之內。下面的腳本實現的是:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Check whether a label name has been delivered: 
if "%~1"=="" (
    echo ERROR: No label name specified! 1>&2 
    exit /B 1 
) 

rem /* Call sub-routine to replace the literal label string `:%~1` 
rem within this batch file by the given dynamic label name: */ 
call :REPLACE_LINE "%~f0" ":%%%%~1" ":%~1" || (
    rem /* In case the given label is `:REPLACE_TEXT`, display error 
    rem message, clean up temporary file and quit script: */ 
    >&2 echo ERROR: Label ":%~1" is already defined! 
    2> nul del "%~f0.tmp" 
    exit /B 1 
) 

rem // Perform call of the sub-routine with the dynamic label name: 
call :%~1 

rem /* Call sub-routine to replace the given dynamic label name 
rem within this batch file by the literal label string `:%~1`: */ 
call :REPLACE_LINE "%~f0" ":%~1" ":%%%%~1" 

endlocal 
exit /B 


:REPLACE_LINE val_file_path val_line_LOLD val_line_LNEW 
    ::This sub-routine searches a file for a certain line 
    ::case-insensitively and replaces it by another line. 
    ::ARGUMENTS: 
    :: val_file_path path to the file; 
    :: val_line_LOLD line to search for; 
    :: val_line_LNEW line to replace the found line; 
    setlocal DisableDelayedExpansion 
    rem // Store provided arguments: 
    set "FILE=%~1" & rem // (path of the file to replace lines) 
    set "LOLD=%~2" & rem // (line string to search for) 
    set "LNEW=%~3" & rem // (line string to replace the found line) 
    set "LLOC=%~0" & rem // (label of this sub-routine) 
    rem // Write output to temporary file: 
    > "%FILE%.tmp" (
     rem /* Read the file line by line; precede each line by a 
     rem line number and `:`, so empty lines do not appear as 
     rem empty to `for /F`, as this would ignore them: */ 
     for /F "delims=" %%L in ('findstr /N "^" "%FILE%"') do (
      rem // Store current line with the line number prefix: 
      set "LINE=%%L" 
      setlocal EnableDelayedExpansion 
      rem // Check current line against search string: 
      if /I "!LINE:*:=!"=="!LOLD!" (
       rem // Current line equals search string, so replace: 
       echo(!LNEW! 
      ) else if /I not "!LNEW!"=="!LLOC!" (
       rem // Current line is different, so keep it: 
       echo(!LINE:*:=! 
      ) else (
       rem /* Current line equals label of this sub-routine, 
       rem so terminate this and return with error: */ 
       exit /B 1 
      ) 
      endlocal 
     ) 
    ) 
    rem /* Searching and replacement finished, so move temporary file 
    rem onto original one, thus overwriting it: */ 
    > nul move /Y "%FILE%.tmp" "%FILE%" 
    endlocal 
    exit /B 


:%~1 
    ::This is the sub-routine with the dynamic label. 
    ::Note that it must be placed after all the other code! 
    echo Sub-routine. 
    exit /B 

基本上,它首先替換文字標籤字符串(線):%~1由作爲第一命令行參數提供的字符串,然後它調用部通過call :%~1,最後,它恢復原始文字標籤字符串。替換由子程序:REPLACE_LINE管理。

+0

目的簡而言之:我有一堆構建腳本(.bat文件),一些知道如何:構建,一些如何:配置,一些如何:安裝......這些代碼是由所有人運行的(調用commonfoo.bat%*)與所有參數,所以這個中央蝙蝠應該能夠調用回調用文件...希望,使其更容易理解 – santa

+0

我想我可以easlily適應這個腳本添加標籤,如果他們缺少並跳過清理部分,以便通用腳本在使用時能夠學習所需的標籤 – santa

0

foo.bat(次)通過:

@echo off 
echo this is foo.bat 
REM check, if the label is defined in this script: 
findstr /xi "%~1" %~f0 >nul 2>&1 || goto :error 
goto %~1 

:foo 
echo  reached foo.bat, label :foo 
exit /b 0 

:error 
echo  wrong or missing label: "%~1" 
exit /b 1 

bar.bat(主)

@echo off 
echo this is bar.bat 
call foo.bat :foo 
echo back to bar.bat - %errorlevel% 
call foo.bat :foe 
echo back to bar.bat - %errorlevel% 
call foo.bat 
echo back to bar.bat - %errorlevel% 
exit /b 
1

您可以使用批處理解析器伎倆。
你不需要做任何事情在foo.bat這工作

::foo.bat 
echo.wont be executed 
exit /b 1 
:func1 
echo foo from foo.bat 
exit /b 0 

:unknown 
echo Hello from %0 Func :unknown 
exit /b 

你只需要任何標籤添加到bar.bat要調用foo.bat

@echo off 
::bar.bat 
call :unknown 
echo Back from Foo 
call :func1 
echo Back from Foo 
exit /b %errorlevel% 

:unknown 
:func1 
foo.bat 
echo NEVER COMES BACK HERE 

訣竅是,在調用bar.bat中的標籤後,啓動foo.bat 而不調用(僅限於foo.bat),foo.bat被加載,最後被調用的標籤被跳轉到。

0

由於aschipfl已經正確說明你不能有一個動態標籤,但你可以動態調用當前標籤,但你應該先檢查它是否存在,然後像Stephan那樣調用它,但是在主批次中。
所以這是Stephans和jebs批次的組合。

:: bar.bat 
@echo off 
REM check, if the label is defined in this script: 
If "%~1" neq "" findstr /xi "%~1" %~f0 >nul 2>&1||goto :error&&Call :%~1 
call :Func1 
echo Back from Foo 
call :func2 
echo Back from Foo 
exit /b %errorlevel% 

:error 
echo  wrong or missing label: "%~1" 
exit /b 1 

:func1 
:func2 
foo.bat 
echo NEVER COMES BACK HERE 

:: foo.bat 
@Goto :Eof 

:func1 
echo  reached foo.bat, label :func1 
exit /b 0 

:func2 
echo  reached foo.bat, label :func2 
exit /b 0 

輸出示例:

> bar 
    reached foo.bat, label :func1 
Back from Foo 
    reached foo.bat, label :func2 
Back from Foo 

> bar fx 
     wrong or missing label: "fx"