@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.
@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.
Проблема заключается в том, что вы используете %m%
внутри цикла for
. Это оценивается при чтении цикла (перед любыми итерациями вообще). Другими словами, весь цикл, вплоть до закрывающей круглой скобки, считывается и оценивается перед выполнением. Таким образом, %m%
всегда будет исходным значением независимо от того, что вы на самом деле установили в цикле.
Примером может служить иллюстрация:
set val=7
for %%i in (1) do (
set val=99
echo %val%
)
echo %val%
что приводит к неожиданному (для некоторых):
7
99
просто потому, что интерпретируется %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
, поэтому, когда эта строка интерпретируется:
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
UPDATE: для поиска максимального значения 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 & ")"
Выход
C:\test>type file
422,34
464,55
455,65
421,88
C:\test>cscript //nologo test.vbs file
Max is 464 (line: 2)