如何在当前批处理中调用另一个批处理文件中定义的函数?

发布于 2025-01-20 00:26:00 字数 732 浏览 0 评论 0 原文

我知道我可以使用 call path_to_other_batch_file.bat 调用另一个批处理文件。

但是,我不知道如何调用该文件内的函数。

我有一个名为 Message.bat 的批处理文件:

@echo off

EXIT /B %ERRORLEVEL%

:Error
echo [31m %* [0m
EXIT /B 0

:Warning
echo [33m %* [0m
EXIT /B 0

:Info
echo [34m %* [0m
EXIT /B 0

:Success
echo [32m %* [0m
EXIT /B 0

:Reset
echo [37m %* [0m
EXIT /B 0

我想在其他批处理文件中使用这些函数,这样我就可以简单地编写 call:Error Something goneError 而不必担心一直与颜色有关。

我在 Other.bat 中以这种方式使用它,但它不起作用:

call C:\Infra\Message.bat
call:Error something went wrong

我收到此错误:

系统找不到指定的批次标签 - 错误

那么,如何调用 Message.bat 文件中定义的这些方法呢?

I know that I can call another batch file using call path_to_other_batch_file.bat.

However, I don't know how can I call functions inside that file.

I have this batch file called Message.bat:

@echo off

EXIT /B %ERRORLEVEL%

:Error
echo [31m %* [0m
EXIT /B 0

:Warning
echo [33m %* [0m
EXIT /B 0

:Info
echo [34m %* [0m
EXIT /B 0

:Success
echo [32m %* [0m
EXIT /B 0

:Reset
echo [37m %* [0m
EXIT /B 0

And I want to use these functions in my other batch files so that I can simply write call:Error something went wrong without worrying about colors all the time.

I use it this way in Other.bat, but it does not work:

call C:\Infra\Message.bat
call:Error something went wrong

I receive this error:

The system cannot find the batch label specified - Error

So, how can I call those methods defined in my Message.bat file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小鸟爱天空丶 2025-01-27 00:26:00

在你的主要批次中

call message error something went wrong

在消息中

@echo off
goto %1

:error
for /f "tokens=1*" %%L in ("%*") do echo %%M
exit /b 0

确实没那么难...

或者,在 message.bat 中更好

@echo off
FOR /f "tokens=1*" %%L IN ("%*") DO CALL :%%L %%M
EXIT /B %ERRORLEVEL%

:Error
echo [31m %* [0m
EXIT /B 0

:Warning

...

In your main batch(es)

call message error something went wrong

In message

@echo off
goto %1

:error
for /f "tokens=1*" %%L in ("%*") do echo %%M
exit /b 0

really not that hard...

or, better in message.bat

@echo off
FOR /f "tokens=1*" %%L IN ("%*") DO CALL :%%L %%M
EXIT /B %ERRORLEVEL%

:Error
echo [31m %* [0m
EXIT /B 0

:Warning

...

小傻瓜 2025-01-27 00:26:00

(至少)有两种可能性,其中一种是由 jeb 提供的"https://stackoverflow.com/a/60040042" title="为什么我们不能在 FORFILES 脚本中使用 CALL :label 命令?">他的这个回答 – 所以请给予他足够的信任通过投票支持他的 邮政!

main.bat,在sub.bat中建立两次标签:Label的调用:

@echo off
echo/
echo ^>^>^> Supply `:Label` as the first argument:
call "%~dp0sub.bat" :Label arg1 arg2 arg3
echo ^>^>^> Returned to main script at this point.
echo/
echo ^>^>^> Embed `:Label` within the script path:
call "%~d0\:Label:\..%~p0sub.bat" arg1 arg2 arg3
echo ^>^>^> Returned to main script at this point.
exit /B

sub.bat,以两种不同的方式解析标签 :Label

@echo off
echo Original path: "%~0"
echo Resolved path: "%~f0"
echo 1st argument : "%~1"
echo All arguments: %*
rem // Check whether first argument begins with (a) colon(s):
for /F "tokens=* delims=:" %%L in ("%~1") do if not "%%~L"=="%~1" goto :%%~L
rem // Check whether script path contains something between colons behind the drive:
for /F "tokens=3 delims=:" %%L in ("%~0") do goto :%%~L
rem // This code in the main section is never reached when a label has been provided.
exit /B

:Label
echo Function call: "%~f0" %*
exit /B

这是运行 main.bat 时的控制台输出:

>>>>提供 `:Label` 作为第一个参数:
原始路径:“C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat”
解析路径:“C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat”
第一个参数:“:标签”
所有参数: :Label arg1 arg2 arg3
函数调用: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" :Label arg1 arg2 arg3
>>>>>此时返回到主脚本。

>>>>>在脚本路径中嵌入`:Label`:
原始路径:“C:\:Label:\..\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat”
解析路径:“C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat”
第一个参数:“arg1”
所有参数:arg1 arg2 arg3
函数调用:“C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat” arg1 arg2 arg3
>>>>>此时返回到主脚本。

您可能已经注意到,在第一次调用中,标签 :Label 也是参数字符串 %* 的一部分,您必须特别注意,尽管在第二次调用(应用所述 jeb 的方法),%* 包含纯没有额外项目的参数字符串。

There are (at least) the two possibilities, one of which is courtesy of user jeb in this answer of him – so please give adequate credit to him by up-voting his post!

main.bat, establishing two calls of label :Label in sub.bat:

@echo off
echo/
echo ^>^>^> Supply `:Label` as the first argument:
call "%~dp0sub.bat" :Label arg1 arg2 arg3
echo ^>^>^> Returned to main script at this point.
echo/
echo ^>^>^> Embed `:Label` within the script path:
call "%~d0\:Label:\..%~p0sub.bat" arg1 arg2 arg3
echo ^>^>^> Returned to main script at this point.
exit /B

sub.bat, resolving label :Label in two distinct ways:

@echo off
echo Original path: "%~0"
echo Resolved path: "%~f0"
echo 1st argument : "%~1"
echo All arguments: %*
rem // Check whether first argument begins with (a) colon(s):
for /F "tokens=* delims=:" %%L in ("%~1") do if not "%%~L"=="%~1" goto :%%~L
rem // Check whether script path contains something between colons behind the drive:
for /F "tokens=3 delims=:" %%L in ("%~0") do goto :%%~L
rem // This code in the main section is never reached when a label has been provided.
exit /B

:Label
echo Function call: "%~f0" %*
exit /B

And this is the console output upon running main.bat:

>>> Supply `:Label` as the first argument:
Original path: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat"
Resolved path: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat"
1st argument : ":Label"
All arguments: :Label arg1 arg2 arg3
Function call: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" :Label arg1 arg2 arg3
>>> Returned to main script at this point.

>>> Embed `:Label` within the script path:
Original path: "C:\:Label:\..\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat"
Resolved path: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat"
1st argument : "arg1"
All arguments: arg1 arg2 arg3
Function call: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" arg1 arg2 arg3
>>> Returned to main script at this point.

As you may have noticed, in the first call, the label :Label is also part of the argument string %* which you have to pay specific attention to, though in the second call (applying said jeb's method), %* contains the pure argument string without an extra item.

乖乖哒 2025-01-27 00:26:00

如果您有多个选项,标签有时会变得混乱。如果某些任务满足标准,那么这对于多项任务很有用,但您似乎只想更改事件的颜色。所以我只想说根本不要使用标签。 message.bat 的内容添加:

@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "e=%%a"
if "%1" == "" exit /b 1
set "line=%*"
set "label=%1"
call set "rest=%%line:%label% =%%"

if /i "%1" == "Error" set "severity=[31m%rest%"
if /i "%1" == "Warning" set "severity=[33m%rest%"
if /i "%1" == "Info" set "severity=[34m%rest%"
if /i "%1" == "Success" set "severity=[32m%rest%"
if /i "%1" == "Reset" set "severity=[37m%rest%"

echo %e%%severity%%e%[0m
exit /b 0

要从另一个批次中调用此内容,只需执行以下操作:

call messages.bat warning something went wrong

您很可能也想将实际的严重性添加到消息中,而不仅仅是更改文本颜色,然后简单地将范围缩小到:

@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "e=%%a"
if "%1" == "" exit /b 1

if /i "%1" == "Error" set "severity=[31m%*"
if /i "%1" == "Warning" set "severity=[33m%*"
if /i "%1" == "Info" set "severity=[34m%*"
if /i "%1" == "Success" set "severity=[32m%*"
if /i "%1" == "Reset" set "severity=[37m%*"

echo %e%%severity%%e%[0m
exit /b 0

Labels can sometimes become cluttered if you have multiple options. It is good for multiple tasks if some meets the criteria, but you seem to only want to change colors on events. So I will simply say do not use labels at all. The content of message.bat add:

@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "e=%%a"
if "%1" == "" exit /b 1
set "line=%*"
set "label=%1"
call set "rest=%%line:%label% =%%"

if /i "%1" == "Error" set "severity=[31m%rest%"
if /i "%1" == "Warning" set "severity=[33m%rest%"
if /i "%1" == "Info" set "severity=[34m%rest%"
if /i "%1" == "Success" set "severity=[32m%rest%"
if /i "%1" == "Reset" set "severity=[37m%rest%"

echo %e%%severity%%e%[0m
exit /b 0

To call this from another batch, simply do:

call messages.bat warning something went wrong

There is an odd chance that you want to add the actual severities into the message as well, and not just change the text color, then simply narrow it down to:

@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "e=%%a"
if "%1" == "" exit /b 1

if /i "%1" == "Error" set "severity=[31m%*"
if /i "%1" == "Warning" set "severity=[33m%*"
if /i "%1" == "Info" set "severity=[34m%*"
if /i "%1" == "Success" set "severity=[32m%*"
if /i "%1" == "Reset" set "severity=[37m%*"

echo %e%%severity%%e%[0m
exit /b 0
作妖 2025-01-27 00:26:00

没有内在的方法可以做到这一点。 呼叫将在当前文件中调用外部文件,内部命令或标签

但是,如果您可以更改 message.bat ,则可以使其添加其他参数,呼叫 IT。然后,呼叫将在自己的标签中搜索。

您必须格外小心,而不是将第一个参数传递给标签。为此,您可以使用

@echo off

set "fn=%1"
shift

::"exit /b" is the same as "exit /b %errorlevel%"
if "%fn%"=="" exit /b

set "line=%1"
:loop
shift
if not "%1"=="" (
  set "line=%line% %1"
  goto :loop
)
call :%fn% %line%
exit /b

:Error
echo [31m %* [0m
EXIT /B 0

:Warning
echo [33m %* [0m
EXIT /B 0

:Info
echo [34m %* [0m
EXIT /B 0

:Success
echo [32m %* [0m
EXIT /B 0

:Reset
echo [37m %* [0m
EXIT /B 0

call message.bat error Something went wrong

There's no built-in way to do that. call will either call an external file, an internal command or a label in the current file.

But, if you can change message.bat, you can make it take an additional argument, and call it. Then call will search in its own labels.

You'll have to take extra care to not pass the first argument to the label. For that, you can use the code from this answer:

@echo off

set "fn=%1"
shift

::"exit /b" is the same as "exit /b %errorlevel%"
if "%fn%"=="" exit /b

set "line=%1"
:loop
shift
if not "%1"=="" (
  set "line=%line% %1"
  goto :loop
)
call :%fn% %line%
exit /b

:Error
echo [31m %* [0m
EXIT /B 0

:Warning
echo [33m %* [0m
EXIT /B 0

:Info
echo [34m %* [0m
EXIT /B 0

:Success
echo [32m %* [0m
EXIT /B 0

:Reset
echo [37m %* [0m
EXIT /B 0

Then, you can call it like:

call message.bat error Something went wrong
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文