如何使 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,3
和 1 2=3
-> 2=3
.
如果将2=3
传递给另一个批处理脚本,保留2=3
是没有意义的,因为批处理会将其解析为2
和3
两个参数。批处理令牌分隔符为,
、;
、=
、<space>
、<tab>
。如果您将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%
但是,如果参数包含特殊字符,例如 ^
、&
、>
、<
、|
,这些字符会被转义而不是引用。
参数处理是 Windows 批处理编程的许多薄弱环节之一。几乎每个解决方案都存在导致问题的异常。
【讨论】:
我写了一个简单的,可以处理任何ascii字符。包括\t
\r
\n
^
Back Slash
和quote
。 github.com/zhanhb/kcptun-sip003-wrapper/blob/v0.1/src/…以上是关于如何使 SHIFT 在批处理文件中与 %* 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
使 Raylib-cs 在 Windows 中与 128 以上的扩展 ascii / unicode 一起工作?
如何使 pyspark 和 ML(无 RDD)与大型 csv 一起工作?