我写了一个小脚本来显示文本文件的每一行,每个行之间有一个随机的暂停:
SET pauseTime=10
SET maxval=20
SET minval=5
FOR /f %%j in (search1.txt) DO (
SET pauseTime=%RANDOM% * (%maxval% - %minval% + 1) / 32768 + %minval%
ECHO.%pauseTime%
TIMEOUT %pauseTime%
ECHO.%%j
)
在cmd.exe中运行它给了我:
C:\ Users \ Tim \ Desktop> SET minval = 5
/此时出乎意料。
但是,如果我只是这样做:
FOR /f %%j in (search1.txt) DO (
ECHO.%%j
)
我打印的所有行都没有错误
发生了什么事?
答案 0 :(得分:3)
您需要将/A
开关添加到SET
语句才能进行数学运算。 (我通常还必须删除任何嵌入的空格以使其正常工作。)
SET /A pausetime=%RANDOM%*(%maxval%)-%minval%)/32768+%minval%
您获得的错误也是由批处理器未正确处理for
表达式(数字表达式中的嵌套对)中的括号引起的。您可以通过将表达式的那部分分解为单独的变量,然后使用该变量代替括号内的部分来解决这个问题:
SET pauseTime=10
SET maxval=20
SET minval=5
SET /A maxmin=%maxval% - %minval% + 1
FOR /f %%j in (search1.txt) DO (
SET /A pauseTime=%RANDOM% * %maxmin% / 32768 + %minval%
ECHO. %pauseTime%
TIMEOUT %pauseTime%
ECHO. %j%
)
答案 1 :(得分:1)
这里的问题是因为您使用嵌套( )
括号,批处理无法处理并导致您的问题,您可能需要将暂停时间计算拆分为2行。
在评估括号时,CMD shell语句不会使用任何强大的智能,因此例如下面的命令将失败:
如果存在MyFile.txt(ECHO一些(更多)土豆)
答案 2 :(得分:1)
如其他答案所述,问题是由嵌套的括号引起的。
您可以通过前面的^
个字符逃避而不是避开它们 - 这可行:
IF EXIST MyFile.txt (ECHO Some^(More^)Potatoes)
如果没有插入符号^
,命令行解释器将使用第一个)
关闭第一个(
。
但是,将上述转义技术应用于原始问题的代码可以避免错误消息,但不会导致工作脚本,即使内部SET
被替换为SET /a
(如@KenWhite所述),因为你需要建立delayed environment variable expansion;否则,显示的pauseTime
值始终是初始值10
。以下修复有效:
@ECHO OFF
SET pauseTime=10
SET maxval=20
SET minval=5
SETLOCAL EnableDelayedExpansion
FOR /f %%j in (search1.txt) DO (
SET /a pauseTime=!RANDOM!*^(maxval-minval+1^)/32768+minval
ECHO.!pauseTime!
TIMEOUT !pauseTime!
ECHO.%%j
)
ENDLOCAL
此处,SETLOCAL
语句在FOR
命令执行之前启用延迟扩展。在FOR
循环的正文中,%pauseTime%
和%RANDOM%
分别由!pauseTime!
和!RANDOM!
取代;那些是受延迟扩展的变量(因为包含!!
),这意味着当解析整个FOR
命令时,它们不会(像往常一样)扩展,但是当它被执行时。为了易读起见,我从%%
命令中的其他变量中删除了SET /a
,因为当/a
开关存在时不需要它们(请注意,还有一个{{} 1}}运营商支持!!)。
注意:此脚本运行后,%
会重置为初始值pauseTime
,因为10
/ SETLOCAL
块构成了新的本地化环境命名空如果您需要最后一个值,请将ENDLOCAL
替换为ENDLOCAL
;这利用了标准的立即扩展...
尽管如此,由于ENDLOCAL & SET pauseTime=%pauseTime%
和minval
是脚本中的常量,因此只能在maxval
之外进行一次计算maxval-minval+1
,这与@KenWhite建议的一样。