web-dev-qa-db-ja.com

現時点では、%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.
11
stack

問題は、forループ内で%m%を使用していることです。これは、ループが読み取られたとき(反復の前)に評価されます。言い換えると、閉じ括弧までのループ全体が読み取られ、実行前に評価されます。したがって、%m%は、ループ内で実際に何に設定しても、常に初期値になります。

例がこれをうまく説明するはずです:

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

これは予期しない結果になります(一部の人にとって):

7
99

最初のechoステートメントの%val%が実行される前に解釈される(つまり、forループ全体が解釈される)からです。

mの値を最初の%%xに強制的に設定するものとともに、遅延拡張が必要です。 !m!の代わりにsetlocalコマンドと%m%を使用すると、行が実行されるたびにmの評価が遅れます。

さらに、最初はmをゼロに設定し、それが_is何もないときに%%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
19
paxdiablo

M setという名前の環境変数がないため、この行を解釈すると次のようになります。

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
2
Michael Burr

問題は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)
0
ghostdog74