此时%x出乎意料。批处理脚本

时间:2010-02-03 07:21:20

标签: windows batch-file cmd

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

3 个答案:

答案 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)