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

Posted

技术标签:

【中文标题】如何使 SHIFT 在批处理文件中与 %* 一起使用【英文标题】:How to make SHIFT work with %* in batch files 【发布时间】:2012-03-10 21:48:36 【问题描述】:

在我的 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

我怎样才能达到预期的效果?谢谢!!

【问题讨论】:

【参考方案1】:

这很简单:

setlocal ENABLEDELAYEDEXPANSION
  set "_args=%*"
  set "_args=!_args:*%1 =!"

  echo/%_args%
endlocal

与 cmets 相同:

:: 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

备注:

如果任何参数包含!& 字符则不起作用 不会删除参数之间的任何多余空格 %_args%必须在endlocal之前使用,因为它是一个局部变量 如果没有输入参数,%_args% 返回* = 仅输入 1 个参数时不移位

【讨论】:

您需要删除 %1 参数,而不是 %0(这是脚本的名称) 确实,你是对的。我现在已将 %0 编辑到 %1。谢谢。 正如所写,这是非常危险的错误,因为第一个 arg 的值可能会在后续 arg 中重复,并且您的代码将删除两者。这可以通过使用* 删除第一个实例中的所有内容来解决:set _args=!_args:*%1=!。其他无法修复的问题是如果%1 包含!=,它将失败。 谢谢你,dbenham,我已经根据你的好评论审查了代码。 只是在这里吹毛求疵,@cyberponk,但这并不容易......干得好!【参考方案2】:

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 

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

【讨论】:

【参考方案3】:

全部恢复并修复所有问题:

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

【讨论】:

【参考方案4】:

我最近不得不这样做并想出了这个:

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

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

How to remove trailing and leading whitespace for user-provided input in a batch file?

【讨论】:

【参考方案5】:

另一种简单的方法是:

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

echo/%_args%

备注:

如果第一个参数 (%1) 被“引用”或“双引号”,则不起作用 如果任何参数包含 & 字符则不起作用 不会删除参数之间的任何多余空格

【讨论】:

【参考方案6】:

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

@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

【讨论】:

我看不到临时文件的好处 - set t=%* 也可以。如果 %1 包含 = 或以 *~ 开头,则此答案将失败。如果 args 用 ,; 而不是空格分隔也会有问题。最好只删除 %1 并保留分隔符。 杀手问题 - 如果 args 为 A A B,此答案将给出错误答案。可以通过set t=!t:*%1=!进行改进 使用set "t=!t:*%1=!修改,如果%1包含=,这个答案仍然会失败,但是以*~开头是可以的。 @dbenham:感谢您的反馈!我认为set /p 我只是对某些事情过于谨慎,现在不确定到底是什么,所以你很可能是对的set t=%* 并不比使用临时文件差。我同意你的其他观点。基本上,事实证明,尽管批处理脚本在参数处理方面已经很弱,但我设法在我的建议中增加了更多的克制。 :) 我的脚本比你的脚本有几个(次要)优点:=s 和 , 如果它们不是第一个参数的一部分,则保留它们:1 2,3 -> 2,31 2=3 -> 2=3. 如果将2=3 传递给另一个批处理脚本,保留2=3 是没有意义的,因为批处理会将其解析为23 两个参数。批处理令牌分隔符为,;=&lt;space&gt;&lt;tab&gt;。如果您将2=3 传递给批处理以外的其他内容,那么它可能很重要。【参考方案7】:

如果 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%

但是,如果参数包含特殊字符,例如 ^&amp;&gt;&lt;|,这些字符会被转义而不是引用。

参数处理是 Windows 批处理编程的许多薄弱环节之一。几乎每个解决方案都存在导致问题的异常。

【讨论】:

我写了一个简单的,可以处理任何ascii字符。包括\t\r\n^Back Slashquote。 github.com/zhanhb/kcptun-sip003-wrapper/blob/v0.1/src/…

以上是关于如何使 SHIFT 在批处理文件中与 %* 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使 Raylib-cs 在 Windows 中与 128 以上的扩展 ascii / unicode 一起工作?

如何使更漂亮的(php)与 VS Code 一起工作

如何使 pyspark 和 ML(无 RDD)与大型 csv 一起工作?

MFC——使窗口支持拖拽文件

如何使 ajaxfileupload 与动态生成的文件输入一起工作

如何使 Forge Data Visualization 扩展与 IFC 文件一起使用?