% x был неожиданным в это время.пакетный скрипт - PullRequest
11 голосов
/ 03 февраля 2010
@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 ]

19 голосов
/ 03 февраля 2010

Проблема в том, что вы используете %m% внутри цикла for. Это оценивается, когда цикл читается (перед любыми итерациями вообще). Другими словами, весь цикл, вплоть до закрывающей круглой скобки, читается и оценивается перед выполнением. Таким образом, %m% всегда будет его начальным значением, независимо от того, что вы фактически установили в цикле.

Пример должен, как мы надеемся, проиллюстрировать это:

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

, что приводит к неожиданному (для некоторых):

7
99

просто потому, что %val% в первом операторе echo интерпретируется (т. Е. Интерпретируется весь цикл 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
2 голосов
/ 03 февраля 2010

Не задана переменная окружения с именем M, поэтому при интерпретации этой строки:

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

После 1-го раунда замен интерпретатор выглядит примерно так:

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
0 голосов
/ 03 февраля 2010

Проблема в вашем 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...