%x был неожиданным в это время. пакетный скрипт

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

person stack    schedule 03.02.2010    source источник


Ответы (3)


Проблема в том, что вы используете %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
person paxdiablo    schedule 03.02.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
person Michael Burr    schedule 03.02.2010
comment
Это сообщение об ошибке завершится ошибкой, если M не будет установлено ничего до запуска сценария. Если для переменной M уже установлено что-то, эта ошибка не возникнет (хотя может возникнуть другая ошибка, если для M установлено что-то, что снова делает команду синтаксически неправильной) - person Michael Burr; 03.02.2010
comment
Как удалить % из конца переменной перед сравнением? - person stack; 04.02.2010
comment
как если бы переменные были 50% 60% 70%, я хочу получить самый высокий% !! - person stack; 04.02.2010
comment
@stack - я не уверен, о чем вы спрашиваете в своих последних двух комментариях. При запуске в моей системе пример сценария, который я опубликовал, работает с данными примера, используемыми в других ответах. - person Michael Burr; 04.02.2010
comment
@Michael Я создал отдельный вопрос: stackoverflow.com/questions/ 2197859/ - person stack; 04.02.2010
comment
@Michael Майкл, потому что ваш скрипт не работает со значениями: 12.00,422 5,13,464 15,00,455 14,00,52 13,00,1 Он выдает вывод, поскольку 5 - это максимальное значение из-за сравнения строк, я полагаю. - person stack; 04.02.2010
comment
@stack: да - похоже, что оператор LSS работает со строками (или, может быть, целыми числами или строками). Как я уже говорил в другом месте, пакетные файлы очень плохо справляются со сложной обработкой данных (при очень малом значении комплексности). Я уверен, что эту проблему можно решить, но тогда будет какая-то другая странность пакетных сценариев, из-за которой она падает, когда ваши данные слегка изменяются. Я бы предложил использовать другой инструмент, но если вы настаиваете на использовании пакетных сценариев для этих вещей, возьмите замечательную книгу Тима Хилла по этому вопросу (у продавца, бывшего в употреблении, она может быть очень дешевой): amazon.com/dp/1578700477 - person Michael Burr; 04.02.2010
comment
Отлично, это сэкономило мне время, функция route может помочь мне решить такую ​​​​проблему. - person Larry Cai; 07.12.2010

Проблема в вашем заявлении if %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)
person ghostdog74    schedule 03.02.2010
comment
установка M= не работает, потому что она не принимает максимальное значение! скорее он берет последнее значение из файла. - person stack; 03.02.2010
comment
CSV:-- 422,34 464,55 455,65 421,88 - person stack; 03.02.2010
comment
Хм, этот VBS был бы очень удобен, если бы он действительно делал то же самое, что и файл cmd :-) Файл cmd просто возвращает вам максимальное значение первого «столбца» в csv во всех строках, а не максимальное значение в одной строке. линия. Хотя адаптация не должна быть слишком сложной. - person paxdiablo; 03.02.2010
comment
я понимаю. OP прокомментировал одну строку, поэтому я предположил, что он хочет получить максимум каждой строки (строки). - person ghostdog74; 03.02.2010