类似于批处理文件中的函数/方法?

Something like a function/method in batch files?

提问人:stefan.at.kotlin 提问时间:4/14/2012 更新时间:12/28/2022 访问量:113720

问:

有没有什么东西可以模仿一个方法,比如人们从 Java、C# 等中知道它?我在批处理文件中有 5 行命令,这 5 行在批处理文件中的多个位置使用。我不能使用 goto,因为根据这 5 行创建的 errorlevel,我有不同的操作。我尝试将我的 5 行放在批处理文件中 5lines.bat,但原始批处理文件原始.bat只调用 5lines.bat并且在调用 5lines 后不执行命令.bat ):这就是我的原始.bat的样子:

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

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

Windows 命令行 批处理文件

评论

0赞 bobobobo 12/14/2021
请参阅标记为 CALL a subroutine (:label 的部分

答:

92赞 Erwald 4/14/2012 #1

您可以使用 call 命令:

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

来源 : Batch Functions

评论

9赞 jeb 7/1/2015
goto :eof与 相同,两者都在调用后返回exit /bCALL
0赞 insan-e 12/1/2017
如果我理解正确的话,这就像你从生产线开始称呼同一批次一样。:myDosFunc
0赞 Sandburg 2/1/2019
@jeb它没有达到它的意思吗?无需创建自己的返回积分?
35赞 Cody Gray - on strike 4/14/2012 #2

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

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

call 5lines.bat
echo this will now get called

评论

3赞 Noir 7/6/2019
有趣的是,如果您重命名为,您会注意到这已经足够了,而无需指定扩展名。5lines.bat5lines.cmdcall 5lines
7赞 Attila 4/14/2012 #3

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

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

3赞 jwfearn 4/22/2014 #4

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

24赞 DmitrySemenov 7/1/2015 #5

溶液:

@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%

5赞 npocmaka 1/14/2017 #6

这里有一个“黑客”,可以让你在批处理文件中拥有“匿名”功能

@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 语句结尾

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

53赞 Shital Shah 1/27/2018 #7

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

函数调用

call :myDosFunc 100 "string val"

功能体

:myDosFunc
echo. Got Param#1 %~1
echo. Got Param#2 %~2
goto :eof
3赞 pasha 8/14/2018 #8

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

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%

评论

3赞 Stephan 8/14/2018
为什么要使用? 或者只是“文件结束”会自动返回到旁边的行(这就是 ) 并且不会在堆栈上留下孤立的 JumpBackAddress。它们太多会通过错误消息破坏您的脚本。goto :%returnto%goto :eofcall ...call
7赞 Leon the Logician 10/13/2020 #9

作为 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

下面的代码演示了上述脚本的紧密 Java 等效项。.bat

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);
    }
}
2赞 Carson 11/5/2021 #10

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

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