@echo off
for /f "tokens=1,2 delims=," %%x in (my.csv) do (
if %M% LSS %%x set M=%%x
)
echo Max X Value= %M%
有时它工作正常,有时它失败并出现以下错误:
%x was unexpected at this time.
答案 0 :(得分:19)
问题是您在%m%
循环中使用for
。在读取循环时(在任何迭代之前)评估此值。换句话说,在执行之前读取并评估整个循环,直到并包括右括号。所以%m%
永远是它的初始值,无论你在循环中实际设置它是什么。
一个例子应该有希望说明这一点:
set val=7
for %%i in (1) do (
set val=99
echo %val%
)
echo %val%
导致意外(对某些人):
7
99
只是因为第一个echo语句中的%val%
被解释(即整个for
循环被解释),然后才运行它。
您需要延迟扩展以及强制将m
的值设置为第一个%%x
的内容。使用setlocal
命令和!m!
代替%m%
会延迟m
的评估,直到每次执行该行为止。
此外,将m
初始设置为空,并在 时将其强制为%%x
,将确保将%%x
的第一个值加载到m
。
@echo off
setlocal enableextensions enabledelayedexpansion
set m=
for /f "tokens=1,2 delims=," %%x in (my.csv) do (
if "!m!" == "" set m=%%x
if !m! lss %%x set m=%%x
)
echo Max X Value = !m!
endlocal
将以上代码与此my.csv
文件一起使用:
1,a
2,b
10,c
3,d
导致输出:
Max X Value = 10
符合预期,或者,对于另一条评论中的样本数据:
422,34
464,55
455,65
421,88
你得到:
Max X Value = 464
答案 1 :(得分:2)
没有设置名为M
的环境变量,因此在解释此行时:
if %M% LSS %%x set M=%%x
在第一轮替换之后,它会向解释器看起来像
if LSS %x set M=%x
为避免paxdiablo mentions仅在首次循环时展开%M%
的问题,您可以使用他讨论的延迟扩展功能,或者将测试和设置M
移至从循环调用但存在于循环外部的子例程,以便在每次调用时对其进行解释(和扩展):
@echo off
set M=
for /f "tokens=1,2 delims=," %%x in (my.csv) do (
call :setmax %%x
)
echo Max X Value= %M%
goto :eof
:setmax
if "%M%" == "" set M=%1
if %M% LSS %1 set M=%1
goto :eof
答案 2 :(得分:0)
问题出在您的if %M%
声明中。 %M%在哪里?首先声明它,例如
@echo off
set M=""
for /f "tokens=1,2 delims=," %%x in (file) do (
if %M% LSS %%x set M=%%x
)
echo Max X Value= %M%
替代方案,您可以使用vbscript
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile = objArgs(0)
Set objFile = objFS.OpenTextFile(strFile)
t=0
Do Until objFile.AtEndOfStream
linenum = objFile.Line
strLine = objFile.ReadLine
s = Split(strLine,",")
For Each num In s
WScript.Echo "num "&num
If Int(num) >= t Then
t=Int(num)
End If
Next
WScript.Echo "Max for line:" & linenum & " is " & t
Loop
示例输出
C:\test>type file
422,34464,55455,65421,88
C:\test>cscript //nologo test.vbs file
Max for line:1 is 65421
更新:以列方式查找最大值
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile = objArgs(0)
Set objFile = objFS.OpenTextFile(strFile)
t=0
Do Until objFile.AtEndOfStream
linenum = objFile.Line
strLine = objFile.ReadLine
s = Split(strLine,",")
If Int(s(0)) >= t then
t=Int(s(0))
End If
Loop
WScript.Echo "Max is " & t & " (line: " & linenum & ")"
输出
C:\test>type file
422,34
464,55
455,65
421,88
C:\test>cscript //nologo test.vbs file
Max is 464 (line: 2)