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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2190295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:06:08  来源:igfitidea点击:

%x was unexpected at this time. batch script

windowsbatch-filecmd

提问by stack

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

Sometimes it works fine, sometimes it fails with following error:

有时它工作正常,有时它会失败并出现以下错误:

%x was unexpected at this time.

回答by paxdiablo

The problem is that you're using %m%inside a forloop. This is evaluated when the loop is read (before any iterations at all). In other words, the entire loop, up to and including the closing parenthesis, is read and evaluated before executing. So %m%will always be it's initial value no matter what you actually set it to within the loop.

问题是,你使用%m%一个内for循环。这是在读取循环时(在任何迭代之前)进行评估的。换句话说,在执行之前读取和评估整个循环,直到并包括右括号。因此,%m%无论您在循环中实际将其设置为什么,都将始终是它的初始值。

An example should hopefully illustrate this:

一个例子应该可以说明这一点:

set val=7
for %%i in (1) do (
    set val=99
    echo %val%
)
echo %val%

which results in the unexpected (to some):

这导致意外(对某些人):

7
99

simply because the %val%in the first echo statement is interpreted (i.e., the entire forloop is interpreted) before any of it is run.

仅仅是因为%val%第一个 echo 语句中的 被解释(即,整个for循环被解释)在它的任何一个运行之前。

You need delayed expansion along with something that will force the value of mto be set to the first %%xregardless. Using the setlocalcommand and !m!instead of %m%will delay evaluation of muntil each time the line is executed.

您需要延迟扩展以及强制将 的值m设置为第一个的东西%%x。使用setlocal命令 and!m!而不是%m%将延迟评估,m直到每次执行该行。

In addition, setting minitially to nothing and forcing it to be %%xwhen it isnothing will ensure the first value of %%xis loaded into 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

Using the above code with this my.csvfile:

在此my.csv文件中使用上述代码:

1,a
2,b
10,c
3,d

results in the output of:

导致输出:

Max X Value = 10

as expected or, for your sample data in another comment:

正如预期的那样,或者,对于您在另一条评论中的示例数据:

422,34
464,55
455,65
421,88

you get:

你得到:

Max X Value = 464

回答by Michael Burr

There's no environment variable named Mset, so when this line is interpreted:

没有名为Mset的环境变量,因此在解释此行时:

if %M% LSS %%x set M=%%x

After the 1st round of replacements, it looks to the interpreter something like

在第一轮替换之后,它看起来像解释器

if LSS %x set M=%x

To avoid the problems that paxdiablo mentionsabout %M%being expanded only when the loop is first you can use the delayed expansion feature that he discusses, or move testing and setting Mto a subroutine that is called from the loop but exists outside the loop so it gets interpreted (and expanded) on each call:

为了避免问题,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

回答by ghostdog74

The problem is in your if %M%statement. Where is %M% ? declare it first eg

问题出在你的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%

Alternative, you can use vbscript

替代方案,您可以使用 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

example output

示例输出

C:\test>type file
422,34464,55455,65421,88

C:\test>cscript //nologo test.vbs file
Max for line:1 is 65421

UPDATE: To find max value column wise

更新:明智地找到最大值列

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 & ")"

output

输出

C:\test>type file
422,34
464,55
455,65
421,88

C:\test>cscript //nologo test.vbs file
Max is 464 (line: 2)