variables与常量的batch file比较失败
我想写一个简单的代码来获得一些很好的“时间戳”。 获取时间到我的两个variablesStart
和End
工作正常。 我也可以打印它为0:0:0。 我想要一个前导零,如果它less于10,但显然我得到一个错误,说'参数10没有find或misstyped'。 我发现这似乎是要比较的variables,但我没有解决这个问题。 有任何想法吗?
@ECHO OFF REM Time Calculation FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /a Start=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100 @ECHO ON ping 8.8.8.8 -n 11 @ECHO OFF FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /a End=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100 set /a Diff=%End%-%Start% set /a Diff=(%Diff%)/100 set /a DiffSec=%Diff%%%60 set /a Diff=(%Diff%-%Diff%%%60)/60 set /a DiffMin=%Diff%%%60 set /a Diff=(%Diff%-%Diff%%%60)/60 set /a DiffHrs=%Diff% ECHO Laufzeit Auftraege loeschen: %DiffHrs%:%DiffMin%:%DiffSec% :: format with leading zeroes if %DiffSec% LSS 10 (ECHO "LESS 10")else %DiffSec% LSS 1 (ECHO "LESS 1") ::if %DiffSec% LSS 10 (set DiffSec=0%DiffSec%)else [%DiffSec%] LSS 1 (set DiffSec=00) ::if %DiffMin% LSS 10 (set DiffMin=0%DiffMin%)else [%DiffMin%] LSS 1 (set DiffMin=00) ::if %DiffHrs% LSS 10 (set DiffHrs=0%DiffHrs%)else [%DiffHrs%] LSS 1 (set DiffHrs=00) ECHO Laufzeit Auftraege loeschen: %DiffHrs%:%DiffMin%:%DiffSec%
1.debuggingbatch file
要debuggingbatch file以在代码中查找语法错误,build议在将每个echo off
修改为echo ON
,从batch file中删除或用命令REM注释掉之后,从命令提示符窗口中运行batch file。
默认情况下,在parsing和预处理之后,Windows命令解释器会输出每个命令行或整个命令块(
以及以匹配结束)
,其中,使用%variable%
(立即扩展)引用的环境variables已经被环境variables的当前值执行命令行/块。
在batch file顶部@echo off
,该默认行为将被closures,从而在命令行开始时@
也会禁用第一个命令行的输出。 batch file的开发完成并且batch file正常工作时,这当然是可喜的。 但是,为了debuggingbatch file不能按预期的方式工作,最好还是通过命令解释程序真正执行命令行来查找batch file执行由于错误而意外退出的位置。
ECHO行为在帮助输出运行echo /?
非常简要的解释echo /?
从命令提示符窗口中。
打开命令提示符窗口将导致使用选项/K
隐式启动cmd.exe
, 以便在batch file或应用程序执行完成后保持命令进程运行并打开控制台窗口。
batch file包含不带参数/B
的命令exit
时是个例外,因为在这种情况下,当前命令进程始终独立于调用层次而退出。 exit /B
是相同的goto :EOF
,应该使用,而不是只是exit
除非有一个真正的理由使用只是exit
。 exit /B
和goto :EOF
需要在Windows上默认启用这两个命令扩展。
双击batch file导致启动cmd.exe
选项/C
closures命令进程及其控制台窗口自动执行应用程序或batch file完成独立于batch file的执行终止的原因。 自动closures控制台窗口的这种行为不适合debuggingbatch file,因为由于语法错误而导致batch file执行终止时无法看到错误消息。
有关Windows命令解释程序选项的更多详细信息,请在命令提示符窗口中运行以下命令: cmd /?
如何使用goto :EOF
(冒号在这里是非常重要的exception方式)或者exit /B
(只是goto :EOF
一个内部别名)来有意解释batch file的执行,这是通过运行goto /?
并exit /?
在命令提示符窗口中。
为了debugging更大的batch file,在batch file的顶部使用暂时添加的goto
来跳转到特定的块并跳转到goto :EOF
可以在块debugging后退出批处理。
顺便说一句::
是一个无效标签,经常用于batch file中的注释,因为标签行从不显示在batch file的执行中。 但是,在FOR循环的命令块中,不能使用标签,因为Windows命令解释器无法正确解释命令块中带有标签的FOR循环。 由于这个原因,最好使用命令REM (备注)作为注释,因为这个命令是为batch file中的注释而devise的,而且真正可以在batch file中的任何地方使用。
2.batch file错误
使用@ECHO OFF
运行@ECHO OFF
文件时,通过在命令提示符窗口中使用rem @echo off
(在文本编辑器中运行replace)replace注释,可以很容易地看到错误发生在哪一行:
if %DiffSec% LSS 10 (ECHO "LESS 10")else %DiffSec% LSS 1 (ECHO "LESS 1")
如果环境variablesDiffSec
当前值不低于10
则ELSE分支由Windows命令解释器执行,该命令解释器以数字10
开头。
Windows命令解释程序无法在当前目录中find具有该名称的应用程序,也不能在环境variablesPATHEXT
以分号分隔的文件扩展名列表中指定了文件扩展名的环境variablesPATH
以分号隔开的目录列表中指定的任何目录中find该应用程序。
错误在这里显然是下一个比较中缺less的IF命令。 所以正确的代码将是
if %DiffSec% LSS 10 (ECHO "LESS 10") else if %DiffSec% LSS 1 ECHO "LESS 1"
在多行上编写条件时,这会更容易阅读:
if %DiffSec% LSS 10 ( ECHO "LESS 10" ) else if %DiffSec% LSS 1 ( ECHO "LESS 1" )
语法现在是正确的。
但是第二个条件没有任何意义,因为JosefZ在他的评论中已经提到了。 如果DiffSec
值为10或更大,导致执行ELSE分支中的IF命令,则这种情况肯定也不会成立。 所以更多的感觉会使:
if %DiffSec% LSS 1 (ECHO LESS 1) else if %DiffSec% LSS 10 ECHO LESS 10
或者,
if %DiffSec% LSS 1 ( ECHO LESS 1 ) else if %DiffSec% LSS 10 ( ECHO LESS 10 )
有关batch file中有效的IF ELSE条件的更多信息,请参阅上面的答案
- batch file中如果ELSE语法错误?
- 批处理脚本 – 如果存在使用adb的./sdcard/file.any
3.为数字<10添加前导零
环境variables始终是stringtypes。 对于算术expression式,环境variables的string值在可能的情况下转换为有符号的32位整数,并将算术expression式的结果从带符号的32位整数转换回string。
还有一个IF条件,例如if %DiffSec% LSS 10
在执行之前展开,例如, if 5 LSS 10
导致从string转换5
(0x35)为整数, 10
(0x31 0x30)也从string转换为整数,整数。
所以如果可能的话,避免这样的数字比较会更快一些。
将一个前导零添加到一个低于10的数字是很容易的,而没有通过使用stringreplace来真正testing数值。
首先,环境variables的当前值被预置为一个(对于两位数字)或更多0
(对于3,4或甚至更多数字)。
set "DiffSec=0%DiffSec%"
接下来,从环境variables的当前值向环境variables分配最后的 X个字符,如2的两位数字。
set "DiffSec=%DiffSec:~-2%"
stringreplace在SET命令的帮助下解释,通过在命令提示符窗口中运行set /?
。
这两行的结果是DiffSec
的值为0
到99
,这两行总是两个数字,范围在00
到99
。
4.parsing算术expression式
一个算术expression式是set /a
之后的string,由Windows命令解释器解释完全不同于其他string。
空格和制表符是单词分隔符,但没有其他特殊含义。 因此,build议使用空格来使算术expression式更易读。
那么有很多操作员在列出的命令SET帮助下显示在运行命令提示符窗口中set /?
。
进一步的十进制,八进制和hex整数在算术expression式中被解释为整数。
最后,每隔一个string被解释为当前值从string转换为整数的环境variables的名称。
因此,在算术expression式中使用立即或延时扩展是不可取的。
在执行第一个命令之前,在环境variables的当前值replace已经parsing整个命令块的variables引用的命令块中使用时,在算术expression式中引用具有%variable%
的环境variables的值是不好的。
使用!variable!
引用环境variables的!variable!
在算术expression式中也是不好的,因为它需要启用延迟扩展,导致处理string中的感叹号不再是字面字符。
所以最好总是简单地写variables名称在算术expression式中,如果由于variables名称不包含百分号或感叹号而不能包含空格字符,并且以不能被Windows解释为整数字符的字符开始命令解释器。
在命令行上使用'set var = text'后 , 为什么在'echo%var%'时没有输出string呢? 有关如何使用set
或set /P
(提示符)或set /A
(算术expression式)将值分配给环境variables的详细信息。
5.修复和优化代码
有问题的代码可以修复和优化到这个代码:
@echo off rem Time Calculation for /F "skip=1 tokens=1-4" %%A in ('%SystemRoot%\System32\wbem\wmic.exe PATH Win32_LocalTime GET Day^,Hour^,Minute^,Second') do ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /A TimeStart=Day * 86400 + Hour * 3600 + Minute *60 + Second @echo on %SystemRoot%\System32\ping.exe 8.8.8.8 -n 11 @echo off for /F "skip=1 tokens=1-4" %%A in ('%SystemRoot%\System32\wbem\wmic.exe PATH Win32_LocalTime GET Day^,Hour^,Minute^,Second') do ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /A TimeEnd=Day * 86400 + Hour * 3600 + Minute *60 + Second set /A TimeDiff=TimeEnd - TimeStart set /A DiffSec=TimeDiff %% 60 set /A TimeDiff=(TimeDiff - DiffSec) / 60 set /A DiffMin= TimeDiff %% 60 set /A DiffHrs=(TimeDiff - DiffMin) / 60 set "DiffSec=0%DiffSec%" set "DiffSec=%DiffSec:~-2%" set "DiffMin=0%DiffMin%" set "DiffMin=%DiffMin:~-2%" set "DiffHrs=0%DiffHrs%" set "DiffHrs=%DiffHrs:~-2%" echo Time needed for orders deletion: %DiffHrs%:%DiffMin%:%DiffSec%
为了理解使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
-
echo /?
-
for /?
-
ping /?
-
rem /?
-
set /?
-
wmic /?
-
wmic path /?
if %DiffSec% LSS 10 (ECHO "LESS 10")else IF %DiffSec% LSS 1 (ECHO "LESS 1")
你需要一个if
在else
。