批处理速记:8个日常实用的批处理技巧






4.69/5 (4投票s)
实用且易于使用的批处理脚本,适合初学者和高级用户
引言
早在 2016 年,我就决定尽可能多地学习批处理文件编程语言,因为批处理是我童年时期的第一门编程语言。今天,我将与您分享一些批处理的技巧。
背景
如果您已经做了一些基本的命令行工作(cmd.exe)和/或编写过基本的批处理文件,请跳过本节。
如果您从未编写过批处理文件,那么欢迎您。只需运行“cmd.exe”打开命令提示符,然后键入:“notepad hello.bat
”。
在记事本中,键入以下内容
@echo off echo Welcome to the Batch Programming World!
关闭记事本并保存文件。现在回到命令提示符,键入:“hello.bat”然后按 Enter 键。
就是这样!这是您的第一个批处理文件脚本,它会输出上面的消息。
建议您了解一些编程概念,以便继续阅读本文的其余部分。
技巧 #1 - 获取用户输入并执行算术运算
通常,编写交互式脚本非常重要,这些脚本可以从用户那里获取输入,并在需要时执行算术运算。
要读取用户输入,我们可以使用以下语法
SET /P VarName=The prompt text
例如,要询问用户的姓名并将其显示回来,我们可以这样做
@echo off setlocal SET /P Name="What is your name? " echo Welcome %Name%
引用在使用“SET”命令时,不要污染环境变量命名空间很重要,因此最好在脚本开头使用“setlocal”命令,该命令将在脚本终止时还原环境变量更改。
同样,要执行算术运算,我们可以使用以下语法
SET /A Number=Expression
例如
SET /A Number=1+2+3+4
将计算出的值“10”存储到变量“Number”中。
现在,我们可以结合这两个技巧来创建一个小型整数表达式计算器
@echo off setlocal :repeat SET /P Expr="Please enter an expression (or 'q') to quit:" SET /A Result=%Expr% if "%Expr%"=="" goto :eof if "%Expr%"=="q" goto :eof echo The result is %Result% goto repeat
以下是此脚本的示例输出
C:\Temp\Batchography>expr-calc.bat Please enter an expression (or 'q') to quit:1+2+3 The result is 6 Please enter an expression (or 'q') to quit:-5+2 The result is -3 Please enter an expression (or 'q') to quit:q C:\Temp\Batchography>
技巧 #2 - 数字计数
数字计数在许多场景中都可能派上用场。它可以用于创建编号的虚拟文件夹,编写需要计数的算法,或任何您可以想到的其他用途。
在批处理文件中,计数可以使用以下语法
FOR /L %variable IN (start, step, end) DO command [command-parameters]
让我们通过编写一个创建 10 个虚拟文件夹的小脚本来演示:“folder1”到“folder10”
假设我们有以下文件
@echo off for /L %%a in (1, 1, 10) do ( mkdir folder%%a )
例如,让我们编写 sigma 函数(执行从 1 到 N 的加法)
@echo off setlocal :repeat SET /P N="Please N for the sigma computation:" SET /A Result=0 for /L %%i in (1, 1, %N%) do ( SET /A Result=Result+%%i ) echo Sigma(%N%)=%Result%
技巧 #3 - 在批处理文件中逐行读取文本文件
一次从一个文本文件读取一行对于文本扫描和转换非常有用。像这样使用“FOR /F”语法
@echo off for /f "delims=" %%a in (the-file.txt) DO ( ECHO Line is: %%a )
我们可以使用批处理语言实现一个非常基本的非空行计数器,如下所示
@echo off setlocal enabledelayedexpansion if "%1"=="" ( echo Please specify a file name! goto :eof ) set /A nlines=0 for /f "delims=" %%a in (%1) DO ( set /A nlines+=1 ) echo Total non-empty lines: %nlines%
引用“FOR /F”将跳过输入文本文件中的空行。
技巧 #4 - 字符串替换
使用批处理脚本语言,可以进行字符串替换。要实现这一点,我们需要将目标字符串保存在一个环境变量中。然后我们可以使用以下语法
%VarName:StringToBeMatched=StringToBeReplacedWith%
让我们编写一个交互式脚本,将文件“email.txt”中的单词“books”替换为“ebooks”
Reading books was the norm during his grandfather's time. People used to carry books with them to school in order to read and study. Some say that books will become obsolete one day. Who knows.
以下脚本将执行字符串替换并生成一个名为“new-email.txt”的新文件
@echo off setlocal enabledelayedexpansion if exist new-email.txt del new-email.txt for /f "delims=" %%a in (email.txt) DO ( set line=%%a echo !line:books=ebooks! >>new-email.txt )
引用我们使用“setlocal enabledelayedexpansion”和“!Var!”语法,而不是在复合语句内部扩展变量时使用“%Var%”语法。
“new-email.txt”的内容是
Reading ebooks was the norm during his grandfather's time. People used to carry ebooks with them to school in order to read and study. Some say that ebooks will become obsolete one day. Who knows.
技巧 #5 - Polyglot 脚本:混合 Python 和批处理文件
一个非常有趣的技巧是,当一个脚本可以在两种或多种语言下成功运行时。让我们说明如何为运行 Python 和批处理文件创建一个混合脚本
@echo off rem = """ :: From here and on, write any Batch file syntax and it will be ignored by Python :: :: The Batchography book by Elias Bachaalany :: python -x "%~f0" %* exit /b %errorlevel% :: End of batch file commands """ # Anything here is interpreted by Python import platform import sys print("Hello world from Python %s!\n" % platform.python_version()) print("The passed arguments are: %s" % sys.argv[1:])
上面的批处理脚本使用“python -x”开关(跳过第一行)再次调用自身作为 Python 脚本。
此类脚本很有用,因为它们首先允许批处理脚本设置或验证正确的环境,然后再调用嵌入的 Python 代码。
技巧 #6 - Polyglot 脚本:自编译的 C++ 和批处理文件
与技巧 #5 类似,我们可以创建一个同时也是 C++ 程序的批处理文件脚本。以下是我们如何创建一个自编译的 C++ 批处理脚本
/* 2>nul && echo | set /p= @echo off setlocal echo. :: :: Self-compiling C++ Batch file! :: :: (c) Batchography book - by Elias Bachaalany :: set outfile="%~dpn0.exe" cl %~dpf0 /TP /EHsc /link /out:%outfile% /nologo > nul if exist %outfile% ( %outfile% del %outfile% del "%~dpn0.obj" ) else ( echo Compilation failed! ) goto :eof */ #include <stdio.h> int main() { printf( "Hello world! I was self-compiled!\n" "\n" "Checkout the Batchography book!\n"); return 0; }
此 polyglot 脚本有一个小缺点。第一行(“/*” C 多行注释的开始)不是一个有效命令,它会导致错误,但我们会将错误重定向到 null 设备。我们在退出批处理文件后不久就用“*/”关闭了多行注释。
技巧 #7 - 对命令输出进行分词
可以执行一个命令,然后将其输出分解成令牌。要实现这一点,我们将使用“FOR /F”语法。
从命令提示符,要查询注册表并检索 语言 ID,我们可以使用“reg.exe”命令,如下所示
C:\Temp\Batchography>reg query "hklm\system\controlset001\control\nls\language" /v Installlanguage HKEY_LOCAL_MACHINE\system\controlset001\control\nls\language Installlanguage REG_SZ 0409 C:\Temp\Batchography>
我们有两个输出行。我们只关心第二行和第 3 个令牌(如果我们使用空格作为分隔符)。要检索 0409 值并编写一个批处理脚本来检测系统语言,我们可以这样做
@echo off for /F "usebackq tokens=3" %%a IN (`reg query "hklm\system\controlset001\control\nls\language" /v Installlanguage`) DO ( set lang_id=%%a ) :: 0409 English ; 0407 German ; 040C French ; 0C0A Spanish if "%lang_id%"=="0409" ( echo English detected ) else if "%lang_id%" == "040C" ( echo French detected ) else ( echo Note: Unknown language ID %lang_id%! )
上面的批处理脚本会过滤出至少包含 3 个令牌的行,并且它只捕获第一个令牌。
技巧 #8 - 函数很有趣
谁说批处理语言是一种简单的语言?您知道可以编写函数(甚至是递归函数)吗?
要定义一个函数,只需创建一个标签然后调用它
@echo off setlocal :main echo Hello! set /p a=Enter the first number: set /p b=Enter thne second number: call :add result %a% %b% echo The result is: %result% goto :eof :add <1=return var> <2=first number> <3=second number> echo Adding '%2' and '%3'. Returning the result into the variable '%1' set /a %1=%2+%3 goto :eof
函数“add”只是一个标签,它后面的同一行内容将被忽略/视为自由文本。惯例上,我们将参数编号及其描述放在这里。“add”函数被定义为接受一个返回变量名(参数 #1)和两个数字“a”(参数 #2)和“b”(参数 #3)。
“main”函数使用“call :func_name”语法并传递后续参数来调用“add”。当“add”返回时,它可以调用“goto :eof”或“exit /b <return_code>”。
结论
批处理编程是一门古老但优美的语言。它有如此多的功能,我很高兴能够对其进行研究和学习。