如何使SHIFT与批处理文件中的%*一起使用

时间:2012-02-20 14:52:18

标签: batch-file windows-xp

在我的Windows XP批处理文件中,我想使用%*扩展到除第一个以外的所有参数。
测试文件 foo.bat < / em>的):

@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

如何达到预期效果?谢谢!

7 个答案:

答案 0 :(得分:20)

如果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 :(得分:3)

不要认为这是一种简单的方法。您可以尝试使用以下解决方法:

@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

答案 2 :(得分:3)

这很简单:

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

<强>说明:

  • 如果任何参数包含,则不起作用!或者&amp;炭
  • 不会删除参数之间的任何额外空格

答案 3 :(得分:1)

我最近必须这样做,并想出了这个:

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

请注意,上面的代码会为新参数添加前导空格。它可以像这样删除:

答案 4 :(得分:1)

DOS / Windows批处理编程的另一个令人讨厌的缺点...

不知道这是否真的比这里的其他答案好,但以为我会分享一些对我有用的东西。此解决方案使用FOR循环而不是goto,并且包含在可重用的批处理脚本中。

单独的批处理脚本“ 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;在此示例中,获取所有参数后的第一个(跳过的)arg:

FOR /f "usebackq delims=" %%i IN (`call shiftn.bat 1 %*`) DO set SHIFTEDARGS=%%i 

也许其他人可以利用此解决方案的某些方面(或提供改进建议)。

答案 5 :(得分:0)

另一种简单的方法是:

set "_args=%*"
set "_args=%_args:* =%"

echo/%_args%

<强>说明:

  • 如果第一个参数(%1)是“引用”或“双引号”
  • ,则不起作用
  • 如果任何参数包含&amp;炭
  • 不会删除参数之间的任何额外空格

答案 6 :(得分:0)

恢复所有问题并解决所有问题:

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