当前位置: 首页 > 面试题库 >

具有常量的变量的批处理文件比较失败

白文彬
2023-03-14
问题内容

我想编写一段简单的代码来获取一些格式良好的“时间戳”。将时间花在我的两个变量上Start,End效果很好。我也可以将其打印为0:0:0。我想要一个小于零的前导零,但是很显然我得到一个错误,说“未找到或错误键入参数10”。我发现这似乎是要比较的变量,但未能解决。有任何想法吗?

@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 

问题答案:

1.调试批处理文件
为了调试批处理文件以查找代码中的语法错误,建议在对批处理文件进行每次echo off修改echo ON或从批处理文件中删除或用命令REM注释掉之后,从命令提示符窗口中运行批处理文件。

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

@echo off在批处理文件的顶部此默认行为,由此断开@在命令行禁用的开始也这个第一命令行的输出。当批处理文件的开发完成并且批处理文件运行正常时,当然欢迎您。但是,对于调试无法按预期方式运行的批处理文件,最好还查看由命令解释器实际执行的命令行,以找出由于错误而意外退出了批处理文件的执行位置。

在ECHO的行为是在帮助输出解释很简单运行echo /?在命令提示符窗口中。

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

批处理文件包含exit不带参数的命令是一个例外,/B因为在这种情况下,当前命令进程始终独立于调用层次结构而退出。exit /B是相等的goto :EOF,应该被用来代替正义,exit除非有充分的理由使用正义exitexit /Bgoto :EOF要求两个命令扩展名均在Windows上默认启用。

在一个批处理文件,结果双击在开始cmd.exe与选项/C,以关闭命令过程和它的控制台窗口会自动在应用程序或批处理文件的执行结束独立于为什么一个批处理文件的执行终止的原因。这种自动关闭控制台窗口的行为不利于调试批处理文件,因为批处理文件执行由于语法错误而终止时,看不到错误消息。

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

在运行时和在命令提示窗口中显示的这两个命令的帮助下,说明了如何使用goto :EOF(冒号在这里很重要,作为例外)或exit /B(只是的内部别名goto :EOF)有意退出批处理文件的执行。goto /?exit /?

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

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

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

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

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

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

此处的错误显然是缺少下一个比较的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在其评论中已经提到的那样。如果值为DiffSec10或更大,导致在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
)

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

批处理文件中是否存在ELSE语法错误?
批处理脚本-如果使用adb存在./sdcard/file.any

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

同样,IF条件(例如if %DiffSec% LSS 10在执行之前扩展)会if 5 LSS 10导致将5(0x35)从字符串转换为整数,以及10(0x31 0x30)也从字符串转换为整数,以便将两个数字作为整数进行比较。

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

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

首先,环境变量的当前值前面加一个(对于两位数的数字)或更大0(对于3、4甚至更多个数字)。

set "DiffSec=0%DiffSec%"

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

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

通过在命令提示符窗口中运行,可以在命令SET输出的帮助下解释字符串替换set /?。

两条线的结果是,DiffSec具有用于值099这两条线总是范围内的两位数字后0099

4.解析算术表达式

set /aWindows命令解释器解释的后跟字符串算术表达式与其他字符串完全不同。

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

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

另外的十进制,八进制和十六进制整数在算术表达式中解释为整数。

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

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

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

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

因此,最好的办法是始终简单地在算术表达式中写变量名,如果可能,因为变量名不包含空格,并且以不能被Windows解释为整数字符的字符开头,则不要在百分号或感叹号周围加上百分号命令解释器。

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

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 /?


 类似资料:
  • 主要内容:命令行参数,set命令,使用数字值,局部与全局变量,使用环境变量批处理文件中有两种类型的变量。 其中一个参数是在调用批处理文件时可以传递的参数,另一个是通过命令完成的。 命令行参数 批处理脚本支持命令行参数的概念,其中参数可以在被调用时传递给批处理文件。参数可以通过变量,,等从批处理文件中调用。 以下示例显示了一个批处理文件,它接受3个命令行参数,并将它们回显到命令行屏幕。 如果上面的批处理脚本存储在一个名为的文件中,我们将运行该批处理 - 以下是批处理文件执

  • 我想创建带有Spring批处理Rest控制器和动态输入文件名的项目。 我的代码:Rest控制器 公共类FileNameController{ } 作业配置: @EnableBatchProcessing公共类JobConfig{ } 我写网址的时候:http://localhost:8080/launch job?fileName=djecc5cpt.csv控制台打印: SQL语法[SELECTJ

  • 我尝试编写了一个简单的批处理文件,您可以在下面看到:

  • 我试图使用精灵套件框架重写简单的游戏(由我前段时间使用Cocos2d Box2d开发)。在Sprite Kit中,一切看起来都简单得多,这很棒,但是我在调整新项目中的物理世界参数时遇到了问题。我注意到使用完全相同的图形图像创建的精灵(都有基本的基于矩形的主体)在精灵套件中的质量比在Cocos2d Box2d中的质量低四倍。将主体密度设置为 4 可以解决问题,不幸的是,这不是主要问题。看起来4倍乘数

  • 我正在尝试在批处理文件中定义和使用变量。看起来应该很简单: 我得到的输出如下: 这是怎么回事?为什么我的变量没有被回声?

  • 我知道匹配模式解析器,这是Spring批处理提供的。我需要关于如何构造批处理作业的帮助,以便它可以读取循环中的记录类型5和记录类型6。