@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.
问题是你正在for
循环中使用%m%
。 当读取循环时(在任何迭代之前),这被评估。 换句话说,直到并包括右括号在内的整个循环在执行之前被读取和评估。 所以%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
没有名为M
set的环境变量,所以当解释这行时:
if %M% LSS %%x set M=%%x
在第一轮替补之后,翻译看起来像这样
if LSS %x set M=%x
为避免paxdiablo提到的有关%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
问题在于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)