在 Windows 命令行的批处理文件中使用参数

在 Windows 中,如何访问批处理文件运行时传递的参数?

例如,假设我有一个名为 hello.bat的程序。在 Windows 命令行输入 hello -a时,如何让程序知道 -a是作为参数传入的?

512682 次浏览

使用变量,例如 .BAT变量,并调用 %0%9

在批处理文件中使用参数:% 0和% 9

批处理文件可以将传入的单词作为带有标记的参数: %0%9

%0 is the program name as it was called.
%1 is the first command line parameter
%2 is the second command line parameter
and so on till %9.

命令行中传递的参数必须是字母数字字符,并用空格分隔。因为 %0是程序名称,所以如果在引导时启动,DOS %0对于 AUTOEXEC.BAT 将是空的。

例如:

在一个名为 mybatch.bat的批处理文件中放入以下命令:

@echo off
@echo hello %1 %2
pause

如下所示调用批处理文件: mybatch john billy将输出:

hello john billy

获取批处理文件的9个以上参数,请使用:% *

百分比之星标记 %*表示“其余的参数”。您可以使用 for 循环来获取它们,如下所示:

Http://www.robvanderwoude.com/parameters.php

关于批处理参数分隔符的注意事项

命令行参数中的一些字符被批处理文件忽略,这取决于 DOS 版本,不管它们是否“转义”,并且通常取决于它们在命令行中的位置:

commas (",") are replaced by spaces, unless they are part of a string in
double quotes


semicolons (";") are replaced by spaces, unless they are part of a string in
double quotes


"=" characters are sometimes replaced by spaces, not if they are part of a
string in double quotes


the first forward slash ("/") is replaced by a space only if it immediately
follows the command, without a leading space


multiple spaces are replaced by a single space, unless they are part of a
string in double quotes


tabs are replaced by a single space


leading spaces before the first command line argument are ignored

批处理文件在程序之后自动传递文本,只要它们是要赋给它们的变量。它们是按照发送顺序传递的; 例如,% 1将是调用程序之后发送的第一个字符串,等等。

如果您有 Hello.bat,其内容是:

@echo off
echo.Hello, %1 thanks for running this batch file (%2)
pause

然后通过以下方式调用命令中的批处理

Hello.bat APerson241% date%

你应该收到这个消息:

您好,APerson241感谢您运行这个批处理文件(01/11/2013)

正如其他人已经说过的,通过命令行传递的参数可以在批处理文件中以 %1%9的符号访问。您还可以使用其他两个标记:

  • %0命令行中指定的可执行文件(批处理文件)名
  • %*命令行中指定的所有参数——如果您想将参数转发给另一个程序,这非常有用。

除了如何访问参数之外,还有许多重要的技术需要注意。

检查是否传递了参数

这是通过像 IF "%~1"==""这样的构造来实现的,当且仅当根本没有传递任何参数时才为真。注意波浪形字符,它会导致 %1值中的任何周围引号被删除; 如果没有波浪形字符,那么如果该值包含双引号(包括语法错误的可能性) ,则会得到意想不到的结果。

处理9个以上的争论(或者仅仅是让生活变得更容易)

如果需要访问9个以上的参数,则必须使用命令 SHIFT。这个命令将所有参数的值移动到一个位置,这样 %0%1的值,%1%2的值,等等。%9获取第十个参数的值(如果有的话) ,这个值在调用 SHIFT之前不能通过任何变量获得(输入命令 SHIFT /?获取更多选项)。

如果您想方便地处理参数,而不需要以特定的顺序显示它们,那么 SHIFT也很有用。例如,脚本可以以任意顺序识别标志 -a-b。在这种情况下,解析命令行的一种好方法是

:parse
IF "%~1"=="" GOTO endparse
IF "%~1"=="-a" REM do something
IF "%~1"=="-b" REM do something else
SHIFT
GOTO parse
:endparse
REM ready for action!

这个方案允许您解析相当复杂的命令行,而不会发疯。

批量参数的替换

对于表示文件名的参数,shell 提供了许多与处理无法以任何其他方式访问的文件相关的功能。通过以 %~开头的构造访问此功能。

例如,要获取作为参数传入的文件的大小,请使用

ECHO %~z1

要获取启动批处理文件的目录的路径(非常有用!) ,可以使用

ECHO %~dp0

您可以通过在命令提示符中键入 CALL /?来查看这些功能的全部范围。

@ Jon 的 :parse/:endparse计划是一个很好的开始,我很感激他的初步通过,但是如果你认为 Windows 的折磨人的批处理系统会让你那么轻松... 好吧,我的朋友,你会大吃一惊的。我花了一整天的时间来研究这个邪恶的东西,在经历了许多痛苦的研究和实验之后,我终于找到了一个可行的实用工具。

假设我们想实现一个实用程序 foobar。它需要一个初始命令。它有一个可选参数 --foo,该参数接受一个 可以选择值(当然,这不能是另一个参数) ; 如果缺少该值,则默认为 default。它还有一个可选参数 --bar,该参数接受 需要值。最后,它可以采取一个标志 --baz没有值允许。这些参数可以按任何顺序排列。

换句话说,它看起来是这样的:

foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]

复杂? 不,这似乎是现实生活中非常典型的公用事业

言归正传,下面是一个解决方案:

@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson


SET CMD=%~1


IF "%CMD%" == "" (
GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=


SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
SHIFT
IF NOT "%ARG%" == "" (
IF NOT "%ARG:~0,2%" == "--" (
SET FOO=%ARG%
SHIFT
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE IF "%PARAM%" == "--bar" (
SHIFT
IF NOT "%ARG%" == "" (
SET BAR=%ARG%
SHIFT
) ELSE (
ECHO Missing bar value. 1>&2
ECHO:
GOTO usage
)
) ELSE IF "%PARAM%" == "--baz" (
SHIFT
SET BAZ=true
) ELSE IF "%PARAM%" == "" (
GOTO endargs
) ELSE (
ECHO Unrecognized option %1. 1>&2
ECHO:
GOTO usage
)
GOTO args
:endargs


ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
ECHO Baz
)


REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof


:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1

是的,真的很糟糕。请参阅我在 https://stackoverflow.com/a/50653047/421049上的类似文章,其中我对逻辑中发生的事情以及为什么使用某些构造提供了更多的分析。

太可怕了,我今天学到的大部分,都很伤人。