具有常量的变量的批处理文件比较失败 [英] Batch file comparison of variable with constant fails

查看:71
本文介绍了具有常量的变量的批处理文件比较失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一段简单的代码来获取一些格式良好的时间戳". 花时间进入我的两个变量StartEnd可以正常工作.我也可以将其打印为0:0:0.我想让前导零小于10,但是很显然我收到一个错误消息,提示未找到或错误键入参数10". 我发现这似乎是要比较的变量,但我没有解决.有什么想法吗?

I want to write a simple piece of code to get some nice formated "time stamp". Getting the time into my two variables Start and End works fine. Also I can print it as 0:0:0. I want to have a leading zero if its less than 10, but apparently I get an error saying 'parameter 10 is not found or misstyped'. I found out that this seems to be the variable to be compared but I failed to fix that. Any ideas?

@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.调试批处理文件

要调试批处理文件以查找代码中的语法错误,建议在将每个echo off修改为echo ON或从批处理文件中删除或用命令<注释掉之后,在命令提示符窗口中运行该批处理文件. strong> REM .

1. Debugging a batch file

For debugging a batch file to find syntax errors in code it is recommended to run the batch file from within a command prompt window after having each echo off modified to echo ON or removed from batch file or commented out with command REM.

默认情况下,Windows命令解释器在解析和预处理(已用%variable%引用的环境变量(立即扩展)已被替换)之前,输出以(开始并以匹配的)结尾的每个命令行或整个命令块.在执行命令行/块之前,环境变量的当前值.

By default Windows command interpreter outputs each command line or an entire command block starting with ( and ending with matching ) after parsing and preprocessing on which environment variables referenced with %variable% (immediate expansion) are already replaced by current value of the environment variable before executing the command line / block.

在批处理文件顶部使用@echo off时,此默认行为已关闭,因此,在命令行开头的@也会禁用此第一个命令行的输出.当批处理文件的开发完成并且批处理文件运行正常时,当然欢迎您.但是对于调试无法按预期方式运行的批处理文件,最好还要查看由命令解释器真正执行的命令行,以找出由于错误而导致批处理文件执行意外退出的地方.

With @echo off at top of the batch file this default behavior is turned off whereby @ at beginning of the command line disables also output of this first command line. That is of course welcome when the development of the batch file is finished and the batch file is working fine. But for debugging a batch file not working as expected it is better to see also the command lines really executed by command interpreter to find out where the batch file execution is exited unexpected because of an error.

在命令提示符窗口中运行echo /?的帮助输出中,非常简要地说明了 ECHO 行为.

The ECHO behavior is explained very briefly in help output on running echo /? from within a command prompt window.

打开命令提示符窗口会导致cmd.exe隐式启动,并带有选项/K保持,该命令进程正在运行,并且控制台窗口在批处理文件或应用程序执行完成之后打开.

Opening a command prompt window results in starting cmd.exe implicitly with option /K to keep the command process running and the console window open after execution of a batch file or application finished.

一个例外是批处理文件包含不带参数/B的命令exit,因为在这种情况下,当前命令进程始终独立于调用层次结构而退出. exit /B等于goto :EOF,应该使用它而不是仅仅使用exit,除非确实有充分的理由只使用exit. exit /Bgoto :EOF都需要Windows上默认启用的两个命令扩展名.

An exception is when the batch file contains the command exit without parameter /B because in this case the current command process is always exited independent on calling hierarchy. exit /B is equal goto :EOF and should be used instead of just exit except there is a really good reason for using just exit. exit /B and goto :EOF require both command extensions as enabled by default on Windows.

双击批处理文件会导致cmd.exe使用选项/C启动以关闭命令进程,并且其应用程序或批处理文件的执行独立于以下原因而自动关闭其控制台窗口:为什么批处理文件的执行终止.自动关闭控制台窗口的行为不适用于调试批处理文件,因为批处理文件由于语法错误而终止执行时,看不到错误消息.

Double clicking on a batch file results in starting cmd.exe with option /C to close command process and its console window automatically when execution of the application or batch file is finished independent on the reason why the execution of a batch file terminated. This behavior with closing automatically the console window is not good for debugging a batch file because the error message can't be seen when batch file execution terminated because of a syntax error.

有关在命令提示符窗口中运行的Windows命令解释器选项的更多详细信息,命令:cmd /?

For more details about options of Windows command interpreter run in a command prompt window the command: cmd /?

在显示的这两个命令的帮助下,说明了如何使用goto :EOF(此处的冒号在例外情况下非常重要)或exit /B(仅是goto :EOF的内部别名)有意退出批处理文件的执行通过在命令提示符窗口中运行goto /?exit /?.

How to exit intentionally the execution of a batch file using goto :EOF (colon is here important by way of exception) or exit /B (just an internal alias for goto :EOF) is explained in help of those two commands displayed by running goto /? and exit /? in a command prompt window.

对于调试更大的批处理文件,使用在批处理文件顶部临时添加的goto跳到某个块,并在要调试的块之后使用goto :EOF退出批处理可能会有所帮助.

For debugging a larger batch file it could be helpful to use a temporarily added goto at top of the batch file to jump to a certain block and a goto :EOF to exit batch processing after the block to debug.

顺便说一句:::是无效的标签,通常用于批处理文件中的注释,因为在执行批处理文件时永远不会显示标签行.但是在 FOR 循环的命令块中,不能使用标签,因为Windows命令解释器无法正确解释在命令块内带有标签的 FOR 循环.因此,最好使用命令 REM (注释)作为注释,因为该命令是为批处理文件中的注释设计的,并且实际上可以在批处理文件中的任何位置使用.

By the way: :: is an invalid label often used for comments in batch files as label lines are never displayed on execution of a batch file. But in the command block of a FOR loop labels can't be used because Windows command interpreter fails to interpret right a FOR loop with labels inside the command block. For that reason it is better to use command REM (remark) for comments as this command is designed for comments in batch files and really work anywhere in a batch file.

在运行有问题的发布的批处理文件时,通过在命令提示符窗口中将其替换为rem @echo off(在文本编辑器中运行替换文件)将两个@ECHO OFF注释掉,可以很容易地看到错误发生在哪一行:

On running the batch file posted in question with both @ECHO OFF commented out by replacing it with rem @echo off (run a replace in text editor) from within a command prompt window it can be seen easily on which line the error occurs:

if %DiffSec% LSS 10 (ECHO "LESS 10")else %DiffSec% LSS 1 (ECHO "LESS 1")

如果环境变量DiffSec的当前值不小于10,则 ELSE 分支由Windows命令解释器执行,该分支以类似10的数字开头.

If current value of environment variable DiffSec is not lower than 10 then the ELSE branch is executed by Windows command interpreter which starts with the number like 10.

Windows命令解释器无法在当前目录或环境变量PATH用分号分隔的目录列表中指定的任何目录中找到具有该名称的应用程序,该目录具有在环境变量PATHEXT的分号分隔的文件扩展名列表中指定的文件扩展名

Windows command interpreter can't find an application with that name in current directory or any directory specified in semicolon separated directory list of environment variable PATH having a file extension specified in semicolon separated file extension list of environment variable PATHEXT.

这里的错误显然是缺少下一个比较的 IF 命令.所以正确的代码应该是

The mistake is here obviously the missing IF command for the next comparison. So the correct code would be

if %DiffSec% LSS 10 (ECHO "LESS 10") else if %DiffSec% LSS 1 ECHO "LESS 1"

在多行写入条件时,这将更容易阅读:

This would be easier to read on writing the condition on multiple lines:

if %DiffSec% LSS 10 (
    ECHO "LESS 10"
) else if %DiffSec% LSS 1 (
    ECHO "LESS 1"
)

语法现在正确.

但是第二个条件没有意义,因为 JosefZ 在他的评论中已经提到.如果DiffSec的值为10或更大,导致在 ELSE 分支中执行了 IF 命令,则此条件绝对也不会成立.这样更有意义:

But the second condition does not make sense as JosefZ mentioned already in his comment. If value of DiffSec is 10 or greater resulting in execution of the IF command in ELSE branch, this condition is definitely also never true. So more sense would make:

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
)

有关批处理文件中有效 IF ELSE 条件的更多信息,请参见例如答案

For more information about valid IF ELSE conditions in batch files see for example the answers on

环境变量始终为字符串类型.对于算术表达式,如果可能的话,将环境变量的字符串值转换为有符号的32位整数,并且将算术表达式的结果从有符号的32位整数转换回字符串.

Environment variables are always of type string. For arithmetic expressions the string value of an environment variable is converted to a signed 32-bit integer if possible at all and the result of the arithmetic expression is converted back from signed 32-bit integer to string.

还有一个 IF 条件,例如if %DiffSec% LSS 10在执行之前被扩展为例如if 5 LSS 10,会导致将5(0x35)从字符串转换为整数,并且将10(0x31 0x30)转换为整数.从字符串到整数,将两个数字作为整数进行比较.

Also an IF condition like if %DiffSec% LSS 10 being expanded before execution for example to if 5 LSS 10 results in converting 5 (0x35) from string to integer and 10 (0x31 0x30) also from string to integer for comparing the two numbers as integers.

因此,如果可能的话,避免这种数字比较会更快一些.

So it would be a bit faster to avoid such a number comparison if that is possible.

在不使用字符串替换真正测试值的情况下,将前导零添加到小于10的数字是很容易的.

It is quite easy to add a leading zero to a number lower than 10 without really testing on value by using string substitution.

首先,环境变量的当前值以一个(两位数字)或多个0(三个,4个甚至更多数字)为前缀.

First the current value of the environment variable is prepended with one (for a two digits number) or more 0 (for 3, 4 or even more digits).

set "DiffSec=0%DiffSec%"

接下来,将最后个X字符(如2表示两位数字)从环境变量的当前值分配到环境变量.

Next the last X characters like 2 for a two digit number are assigned from current value of environment variable to the environment variable.

set "DiffSec=%DiffSec:~-2%"

通过在命令提示符窗口set /?中运行,在命令 SET 输出的帮助下说明了字符串替换.

String substitution is explained in help of command SET output by running in a command prompt window set /?.

这两行的结果是DiffSec的值在099之后的两行中始终是在0099范围内的两位数字.

The result of the two lines is that DiffSec has for values 0 to 99 after those two lines always a two digit number in range 00 to 99.

Windows命令解释器解释的是set /a之后的字符串的算术表达式与其他字符串完全不同.

An arithmetic expression which is the string after set /a is interpreted by Windows command interpreter completely different than other strings.

空格和制表符是单词分隔符,但没有其他特殊含义.因此,建议使用空格使算术表达式更易读.

Spaces and tabs are word separators, but have no further special meaning. Therefore it is advisable to use spaces to make the arithmetic expression better readable.

然后,在命令提示符窗口set /?中运行时显示的命令 SET 帮助中列出了许多运算符.

Then there are a lot of operators which are listed in help of command SET displayed on running in a command prompt window set /?.

更多的十进制,八进制和十六进制整数在算术表达式中被解释为整数.

Further decimal, octal and hexadecimal integers are interpreted in an arithmetic expression as integers.

最后每隔一个字符串将解释为环境变量的名称,该环境变量的当前值从字符串转换为整数.

And last every other string is interpreted as name of an environment variable of which current value is converted from string to integer.

因此,不建议在算术表达式中使用立即扩展或延迟扩展.

For that reason it is not advisable to use immediate or delayed expansion in an arithmetic expression.

在命令块中使用环境变量的当前值替换已经在执行第一个命令之前解析整个命令块时已经引用的变量引用时,在算术表达式中用%variable%引用环境变量的值是不好的命令.

Referencing value of an environment variable with %variable% within an arithmetic expression is not good when used within a command block on which the current value of the environment variable replaces the variable reference already on parsing the entire command block before executing the first command.

在算术表达式中用!variable!引用环境变量的值也不是一件好事,因为它需要启用延迟扩展,从而导致不再将字符串中的感叹号当作文字字符来处理.

Referencing value of an environment variable with !variable! within an arithmetic expression is also not good because it requires enabling delayed expansion which results in handling exclamation marks in strings not anymore as literal characters.

因此,最好的办法是始终简单地在算术表达式中写变量名,并且不要用百分号或感叹号引起,因为变量名不包含空格并且以不能解释为整数的字符开头Windows命令解释器输入字符.

So best is always simply writing the variable names in an arithmetic expression without surrounding percent signs or exclamation marks if that is possible because of variable name does not contain a space character and starting with a character which can't be interpreted as integer character by Windows command interpreter.

另请参见上的答案,为什么在命令行上使用'set var = text'后没有显示'echo%var%'的字符串有关如何仅使用setset /P(提示)或set /A(算术表达式)将值分配给环境变量的详细信息?

See also answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? for details on how to assign a value to an environment variable using just set or set /P (prompt) or set /A (arithmetic expression).

有问题的代码可以对此代码进行固定和优化:

The code in question can be fixed and optimized to this code:

@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%

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • for /?
  • ping /?
  • rem /?
  • set /?
  • wmic /?
  • wmic path /?
  • echo /?
  • for /?
  • ping /?
  • rem /?
  • set /?
  • wmic /?
  • wmic path /?

这篇关于具有常量的变量的批处理文件比较失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆