Windows XPのバッチファイルで、%*
を使用して、最初のパラメーターを除くすべてのパラメーターに展開したいと思います。
テストファイル(foo.bat):
@echo off
echo %*
shift
echo %*
コール:
C:\> foo a b c d e f
実際結果:
a b c d e f
a b c d e f
望ましい結果:
a b c d e f
b c d e f
どうすれば望ましい結果を達成できますか?ありがとう!
CMD.EXEがそのように機能したとしたら、すばらしいことではないでしょうか。残念ながら、あなたが望むことをする良い構文はありません。最善の方法は、コマンドラインを自分で解析し、新しい引数リストを作成することです。
このようなものが機能します。
@echo off
setlocal
echo %*
shift
set "args="
:parse
if "%~1" neq "" (
set args=%args% %1
shift
goto :parse
)
if defined args set args=%args:~1%
echo(%args%
ただし、引数に^
、&
、>
、<
、|
などの特殊文字が含まれていて、引用符ではなくエスケープされている場合、上記には問題があります。
引数の処理は、Windowsバッチプログラミングの多くの弱点の1つです。ほぼすべてのソリューションについて、問題を引き起こす例外が存在します。
それは簡単です:
setlocal ENABLEDELAYEDEXPANSION
set "_args=%*"
set "_args=!_args:*%1 =!"
echo/%_args%
endlocal
コメントと同じこと:
:: Enable use of ! operator for variables (! works as % after % has been processed)
setlocal ENABLEDELAYEDEXPANSION
set "_args=%*"
:: Remove %1 from %*
set "_args=!_args:*%1 =!"
:: The %_args% must be used here, before 'endlocal', as it is a local variable
echo/%_args%
endlocal
例:
lets say %* is "1 2 3 4":
setlocal ENABLEDELAYEDEXPANSION
set "_args=%*" --> _args=1 2 3 4
set "_args=!_args:*%1=!" --> _args=2 3 4
echo/%_args%
endlocal
備考:
そうする簡単な方法があるとは思わないでください。代わりに、次の回避策を試してみてください。
@ECHO OFF
>tmp ECHO(%*
SET /P t=<tmp
SETLOCAL EnableDelayedExpansion
IF DEFINED t SET "t=!t:%1 =!"
ECHO(!t!
例:
test.bat 1 2 3=4
出力:
2 3=4
DOS/Windowsバッチプログラミングのさらに別の厄介な欠点...
これが実際により良いここにある他のいくつかの答えよりも正しいかどうかはわかりませんが、私のために働いているように見える何かを共有したいと思いました。このソリューションは、gotoではなくFORループを使用し、再利用可能なバッチスクリプトに含まれています。
別のバッチスクリプト「shiftn.bat」:
@echo off
setlocal EnableDelayedExpansion
set SHIFTN=%1
FOR %%i IN (%*) DO IF !SHIFTN! GEQ 0 ( set /a SHIFTN=!SHIFTN! - 1 ) ELSE ( set SHIFTEDARGS=!SHIFTEDARGS! %%i )
IF "%SHIFTEDARGS%" NEQ "" echo %SHIFTEDARGS:~1%
別のバッチスクリプトでshiftn.batを使用する方法。この例では、最初の(スキップされた)引数に続くすべての引数を取得します。
FOR /f "usebackq delims=" %%i IN (`call shiftn.bat 1 %*`) DO set SHIFTEDARGS=%%i
おそらく、他の誰かがこのソリューションのいくつかの側面を利用することができます(または改善のための提案を提供することができます)。
私は最近これをしなければならなかった、そしてこれを思いついた:
setlocal EnableDelayedExpansion
rem Number of arguments to skip
set skip=1
for %%a in (%*) do (
if not !position! lss !skip! (
echo Argument: '%%a'
) else (
set /a "position=!position!+1"
)
)
endlocal
ループを使用して、N
の最初の引数をスキップします。引数ごとにコマンドを実行したり、新しい引数リストを作成したりするために使用できます。
setlocal EnableDelayedExpansion
rem Number of arguments to skip
set skip=1
for %%a in (%*) do (
if not !position! lss !skip! (
set args=!args! %%a
) else (
set /a "position=!position!+1"
)
)
echo %args%
endlocal
上記のコードは、新しい引数に先頭のスペースを追加することに注意してください。次のように削除できます。
これを行う別の簡単な方法は次のとおりです。
set "_args=%*"
set "_args=%_args:* =%"
echo/%_args%
備考:
すべてを再開し、すべての問題を修正します。
set Args=%1
:Parse
shift
set First=%1
if not defined First goto :EndParse
set Args=%Args% %First%
goto :Parse
:EndParse
引数間のスペースをサポートしない:1 2 3 4
は1 2 3 4
になります