74

有什么可以模仿 Java、C# 等中的方法吗?我在批处理文件中有 5 行命令,这 5 行在批处理文件中的多个位置使用。我不能使用 goto,因为根据这 5 行创建的错误级别,我有不同的操作。我尝试将我的 5 行放在批处理文件 5lines.bat 中,但原始批处理文件 original.bat 仅调用 5lines.bat 并且在调用 5lines.bat 后不执行命令):这就是我 original.bat 的外观像:

5lines.bat
echo this gets never called, how to make sure this gets called?

5lines.bat 中没有出口或类似的东西!如何确保调用 5lines.bat 之后的行?

4

10 回答 10

88

您可以使用调用命令:

call:myDosFunc

然后以这种方式定义函数:

:myDosFunc    - here starts the function
echo.  here the myDosFunc function is executing a group of commands
echo.  it could do a lot of things
goto:eof

来源:批处理函数

于 2012-04-13T22:42:10.450 回答
40

为了完整起见,您还可以将参数传递给函数:

函数调用

call :myDosFunc 100 "string val"

函数体

:myDosFunc
echo. Got Param#1 %~1
echo. Got Param#2 %~2
goto :eof
于 2018-01-27T11:32:21.650 回答
31

将可重用函数放入单独的批处理文件中肯定可以模拟一个函数。

问题是您必须使用该call命令来确保在第二个批处理文件完成执行后控制权返回给调用者。

call 5lines.bat
echo this will now get called
于 2012-04-13T22:42:22.197 回答
18

解决方案:

@ECHO OFF     

call:header Start Some Operation

... put your business logic here
... make sure EXIT below is present
... so you don't run into actual functions without the call

call:header Operation Finished Successfully

EXIT /B %ERRORLEVEL%

:: Functions

:header
ECHO ================================================= 
ECHO %*
ECHO ================================================= 
EXIT /B 0

将 EXIT /B 放在每个函数的末尾以及函数定义开始之前很重要,在我的示例中是:

退出 /B %ERRORLEVEL%

于 2015-07-01T15:23:34.907 回答
7

您可以尝试使用DOS Batch - Function Tutorial中列出的示例

或者,您可以将公共行放入您从主文件调用的另一个批处理文件中

于 2012-04-13T22:43:18.623 回答
5

这是一个“hack”,可让您在批处理文件中拥有“匿名”功能:

@echo off
setlocal 
set "anonymous=/?"

:: calling the anonymous function
call :%%anonymous%% a b c 3>&1 >nul

:: here the anonymous function is defined
if "%0" == ":%anonymous%" (
  echo(
  echo Anonymous call:
  echo %%1=%1 %%2=%2 %%3=%3
  exit /b 0
)>&3
::end of the anonymous function

匿名功能块应该放在 call 语句之后,并且必须以 exit 语句结束

诀窍是CALL内部使用GOTO然后返回到CALL执行的行。使用双扩展 GOTO 帮助消息被触发(带%%/?%%参数),然后继续脚本。但是在它完成后它会返回到CALL- 这就是为什么需要 if 语句的原因。

于 2017-01-14T15:44:55.117 回答
5

来自 Java 背景,我尝试在为.bat脚本创建过程时加入一些熟悉的约定。

下面的脚本演示了两个过程的定义。

@ECHO OFF
SET firstInstanceVariable="Hello world!"
SET secondInstanceVariable="Good bye world!"
GOTO:MAIN

:firstMethodName
    SETLOCAL ENABLEDELAYEDEXPANSION
        SET firstArgumentPassedIn=%~1
        SET secondArgumentPassedIn=%~2
        
        ECHO %firstInstanceVariable%
        ECHO "The first argument passed in was %firstArgumentPassedIn%"
        ECHO "The second argument passed in was %secondArgumentPassedIn%"
    ENDLOCAL
EXIT /B 0

:secondMethodName
    SETLOCAL ENABLEDELAYEDEXPANSION
        SET firstArgumentPassedIn=%~1
        SET secondArgumentPassedIn=%~2
        
        ECHO %secondInstanceVariable%
        ECHO "The first argument passed in was %firstArgumentPassedIn%"
        ECHO "The second argument passed in was %secondArgumentPassedIn%"
    ENDLOCAL
EXIT /B 0


:MAIN
call:firstMethodName "The Quick Brown" "Fox Jumps Over"
call:secondMethodName "1 2 3 4" 3.14

请注意,GOTO:MAIN跳过过程定义需要显式。这是因为您必须在决定阅读之前跳过该过程。否则,将执行该过程。

下面的代码演示了与上述.bat脚本非常接近的 Java 等效项。

public class MyObject {
    private String firstInstanceVariable = "Hello world!";
    private String secondInstanceVariable = "Good bye world!";
    public void firstMethodName(Object... arguments) {
        String firstArgumentPassedIn = arguments[0].toString();
        String secondArgumentPassedIn = arguments[1].toString();
        System.out.println(firstInstanceVariable);
        System.out.format("The first argument passed in was %s", firstArgumentPassedIn);
        System.out.format("The second argument passed in was %s", secondArgumentPassedIn);
    }

    public void secondMethodName(Object... arguments) {
        String firstArgumentPassedIn = arguments[0].toString();
        String secondArgumentPassedIn = arguments[1].toString();
        System.out.println(secondInstanceVariable);
        System.out.format("The first argument passed in was %s", firstArgumentPassedIn);
        System.out.format("The second argument passed in was %s", secondArgumentPassedIn);
    }

    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        myObject.firstMethodName("The Quick Brown", "Fox Jumps Over");
        myObject.secondMethodName(new Integer[]{1,2,3,4}, 3.14);
    }
}
于 2020-10-12T20:31:00.663 回答
3

有关编写可重用批处理文件代码的另一个很棒的教程 - 请参阅Richie Lawrence 的优秀库

于 2014-04-22T14:47:15.050 回答
3

我不确定其他答案是否很明显,但为了明确起见,我发布了这个答案。我发现其他答案有助于编写以下代码。

echo what
rem the third param gives info to which label it should comeback to
call :myDosFunc 100 "string val" ComeBack

:ComeBack
echo what what
goto :eof

:myDosFunc
echo. Got Param#1 %~1
echo. Got Param#2 %~2
set returnto=%~3
goto :%returnto%
于 2018-08-14T07:41:33.323 回答
0

下面可能使它看起来像一个函数。

call :myFunc %para1% %para2%

:myFunc <para1> <para2>
    echo %1
    echo %2
    EXIT /B

例子

@echo off
echo PROGRAM_NAME:%~nx0 Start
echo.
================================

SET debugMode=%1
call :myFunc1 %debugMode%
call :myFunc2 para1 "para2 hello"

================================
echo PROGRAM_NAME:%~nx0 End & pause>nul
EXIT /B

::  define the function under below
:myFunc1 <isDebug>
    :: So that you can know the %1 means: isDebug.
    if "%1" == "1" (
        echo debug mode
    )
    EXIT /B

:myFunc2 <para1> <para2>
    :: output: para1
    echo %1

    :: output: "para2 hello"
    echo %2
    EXIT /B
于 2021-11-05T09:05:04.457 回答