我有一个批处理文件,我想包含一个包含一些变量(比如配置变量)的外部文件。是否可以?
8 回答
注意:我假设 Windows 批处理文件,因为大多数人似乎没有意识到存在显着差异,只是盲目地在黑色背景 DOS 上用灰色文本调用所有内容。尽管如此,第一个变体也应该在 DOS 中工作。
可执行配置
最简单的方法是将变量本身放入一个批处理文件中,每个变量都有自己的set
语句:
set var1=value1
set var2=value2
...
在您的主要批次中:
call config.cmd
当然,这也可以有条件地或根据系统的各个方面创建变量,因此它非常通用。但是,任意代码可以在那里运行,如果存在语法错误,那么您的主批处理也将退出。在 UNIX 世界中,这似乎相当普遍,尤其是对于 shell。如果你仔细想想,autoexec.bat
没有别的了。
键/值对
var=value
另一种方法是配置文件中的某种对:
var1=value1
var2=value2
...
然后,您可以使用以下代码段来加载它们:
for /f "delims=" %%x in (config.txt) do (set "%%x")
这使用了与以前类似的技巧,即仅set
在每一行上使用。引号用于逃避诸如<
, >
, &
,之类的东西|
。但是,当在输入中使用引号时,它们本身会中断。此外,在进一步处理以此类字符存储的变量中的数据时,您始终需要小心。
一般来说,自动转义任意输入以在批处理文件中不引起头痛或问题对我来说似乎是不可能的。至少我还没有找到这样做的方法。当然,使用第一个解决方案,您将把责任推给编写配置文件的人。
如果外部配置文件也是有效的批处理文件,您可以使用:
call externalconfig.bat
在你的脚本里面。尝试创建以下 a.bat:
@echo off
call b.bat
echo %MYVAR%
和 b.bat:
set MYVAR=test
运行 a.bat 应该会生成输出:
test
Batch 使用小于和大于括号作为输入和输出管道。
>file.ext
仅使用上面的一个输出括号将覆盖该文件中的所有信息。
>>file.ext
使用双右括号会将下一行添加到文件中。
(
echo
echo
)<file.ext
这将根据文件的行执行参数。在这种情况下,我们使用两行将使用“echo”键入。左括号接触右括号意味着来自该文件的信息将通过管道传输到这些行中。
我编译了一个仅供示例的读/写文件。以下是将文件分成几个部分来解释每个部分的作用。
@echo off
echo TEST R/W
set SRU=0
在这个例子中,SRU 可以是任何东西。如果您按 Enter 过快,我们实际上是在设置它以防止崩溃。
set /p SRU=Skip Save? (y):
if %SRU%==y goto read
set input=1
set input2=2
set /p input=INPUT:
set /p input2=INPUT2:
现在,我们需要将变量写入文件。
(echo %input%)> settings.cdb
(echo %input2%)>> settings.cdb
pause
我使用 .cdb 作为“命令数据库”的缩写形式。您可以使用任何扩展名。下一部分是从头开始测试代码。我们不想使用在文件开头运行的设置变量,我们实际上希望它们从我们刚刚编写的 settings.cdb 加载。
:read
(
set /p input=
set /p input2=
)<settings.cdb
因此,我们只是通过管道传输了您在文件开头编写的前两行信息(您可以选择跳过设置行以检查以确保其正常工作)来设置 input 和 input2 的变量。
echo %input%
echo %input2%
pause
if %input%==1 goto newecho
pause
exit
:newecho
echo If you can see this, good job!
pause
exit
这将显示在将 settings.cdb 传送到括号中时设置的信息。作为一个额外的好工作激励因素,按下回车键并设置我们之前设置为“1”的默认值将返回一个好工作消息。使用支架管道是双向的,并且比设置“FOR”的东西要容易得多。:)
所以你只需要这样做吗?:
@echo off
echo text shizzle
echo.
echo pause^>nul (press enter)
pause>nul
REM writing to file
(
echo XD
echo LOL
)>settings.cdb
cls
REM setting the variables out of the file
(
set /p input=
set /p input2=
)<settings.cdb
cls
REM echo'ing the variables
echo variables:
echo %input%
echo %input2%
pause>nul
if %input%==XD goto newecho
DEL settings.cdb
exit
:newecho
cls
echo If you can see this, good job!
DEL settings.cdb
pause>nul
exit
:: savevars.bat
:: Use $ to prefix any important variable to save it for future runs.
@ECHO OFF
SETLOCAL
REM Load variables
IF EXIST config.txt FOR /F "delims=" %%A IN (config.txt) DO SET "%%A"
REM Change variables
IF NOT DEFINED $RunCount (
SET $RunCount=1
) ELSE SET /A $RunCount+=1
REM Display variables
SET $
REM Save variables
SET $>config.txt
ENDLOCAL
PAUSE
EXIT /B
输出:
$RunCount=1
$RunCount=2
$RunCount=3
上述技术也可用于在多个批处理文件之间共享变量。
有点老话题,但几天前我有同样的问题,我想出了另一个想法(也许有人仍然会觉得它有用)
例如,您可以创建一个具有不同主题(家庭、大小、颜色、动物)的 config.bat,并在批处理脚本中以任何您想要的任何顺序单独应用它们:
@echo off
rem Empty the variable to be ready for label config_all
set config_all_selected=
rem Go to the label with the parameter you selected
goto :config_%1
REM This next line is just to go to end of file
REM in case that the parameter %1 is not set
goto :end
REM next label is to jump here and get all variables to be set
:config_all
set config_all_selected=1
:config_family
set mother=Mary
set father=John
set sister=Anna
rem This next line is to skip going to end if config_all label was selected as parameter
if not "%config_all_selected%"=="1" goto :end
:config_test
set "test_parameter_all=2nd set: The 'all' parameter WAS used before this echo"
if not "%config_all_selected%"=="1" goto :end
:config_size
set width=20
set height=40
if not "%config_all_selected%"=="1" goto :end
:config_color
set first_color=blue
set second_color=green
if not "%config_all_selected%"=="1" goto :end
:config_animals
set dog=Max
set cat=Miau
if not "%config_all_selected%"=="1" goto :end
:end
之后,您可以在任何地方使用它,方法是使用 'call config.bat all' 完全调用或仅调用它的一部分(参见下面的示例)这里的想法是,当您可以选择不调用所有内容时,有时会更方便一次。有些变量可能你还不想被调用,所以你可以稍后调用它们。
示例 test.bat
@echo off
rem This is added just to test the all parameter
set "test_parameter_all=1st set: The 'all' parameter was NOT used before this echo"
call config.bat size
echo My birthday present had a width of %width% and a height of %height%
call config.bat family
call config.bat animals
echo Yesterday %father% and %mother% surprised %sister% with a cat named %cat%
echo Her brother wanted the dog %dog%
rem This shows you if the 'all' parameter was or not used (just for testing)
echo %test_parameter_all%
call config.bat color
echo His lucky color is %first_color% even if %second_color% is also nice.
echo.
pause
希望它可以帮助其他人在这里帮助我回答他们的问题。
以上内容的简短版本:
配置文件
@echo off
set config_all_selected=
goto :config_%1
goto :end
:config_all
set config_all_selected=1
:config_family
set mother=Mary
set father=John
set daughter=Anna
if not "%config_all_selected%"=="1" goto :end
:config_size
set width=20
set height=40
if not "%config_all_selected%"=="1" goto :end
:end
测试.bat
@echo off
call config.bat size
echo My birthday present had a width of %width% and a height of %height%
call config.bat family
echo %father% and %mother% have a daughter named %daughter%
echo.
pause
再会。
在我看来,最好的选择是拥有键/值对文件,因为它可以从其他脚本语言中读取。
另一件事是我希望在值文件中有一个注释选项 - 这可以通过命令中的eol
选项轻松实现。for /f
这是示例
值文件:
;;;;;; file with example values ;;;;;;;;
;; Will be processed by a .bat file
;; ';' can be used for commenting a line
First_Value=value001
;;Do not let spaces arround the equal sign
;; As this makes the processing much easier
;; and reliable
Second_Value=%First_Value%_test
;;as call set will be used in reading script
;; refering another variables will be possible.
Third_Value=Something
;;; end
阅读脚本:
@echo off
:::::::::::::::::::::::::::::
set "VALUES_FILE=E:\scripts\example.values"
:::::::::::::::::::::::::::::
FOR /F "usebackq eol=; tokens=* delims=" %%# in (
"%VALUES_FILE%"
) do (
call set "%%#"
)
echo %First_Value% -- %Second_Value% -- %Third_Value%
在尝试使用具有可执行配置的方法时,我注意到它可能工作或可能不工作,具体取决于脚本中调用的位置:
调用 config.cmd
我知道这没有任何意义,但对我来说这是事实。当“call config.cmd”位于脚本顶部时,它可以工作,但如果在脚本中更远,它就不会。
不起作用,我的意思是变量没有在调用脚本中设置。
非常非常奇怪!!!!