【问题标题】:batch parameters: everything after %1批处理参数:%1 之后的所有内容
【发布时间】:2010-10-30 10:53:34
【问题描述】:

重复:

澄清:我知道循环方法 - 这甚至在命令扩展之前就有效;我希望有一些有趣且无证的东西,比如 %~*1 或其他 - 就像在 http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/percent.mspx?mfr=true 记录的那些一样。


在 Windows 批处理文件中(启用了所谓的“命令扩展”),%1 是第一个参数,%2 是第二个参数,以此类推。%* 是所有参数的连接。

我的问题:例如,有没有办法在 %2 之后获取所有内容?

我找不到这样的东西,它会对我正在做的事情有所帮助。

【问题讨论】:

    标签: windows parameters batch-file arguments


    【解决方案1】:

    您可以为此使用 SHIFT。它删除 %1 并将所有其他参数降低一格。此脚本输出 %2 之后的所有参数(因此它输出 %3、%4...),直到其中一个为空(因此它是最后一个):

    @echo off
    
    SHIFT
    SHIFT
    
    :loop
    if "%1" == "" goto end
    echo %1
    SHIFT
    goto loop
    
    :end
    

    编辑:删除了使用 %* 的示例,因为这不起作用 - %* 始终输出所有参数

    【讨论】:

    • 就像在 sh 中一样?伟大的! +1。你碰巧知道什么是 powershell 选项吗?
    • 抱歉,还没用过powershell。
    • 我天真地认为这种方法会奏效,意识到%* 在使用SHIFT 时不会更新,然后然后来到这个 SO 问题寻找解决方案。看起来你做了相反的事情:-p
    【解决方案2】:

    基于 schnaader 的回答,我认为如果您想要连接 %1 之后的所有内容,可以这样做。

    @echo off
    
    SHIFT
    
    set after1=
    
    :loop
    if "%1" == "" goto end
    set after1=%after1% %1
    SHIFT
    goto loop
    
    
    :end
    
    echo %after1%
    

    【讨论】:

      【解决方案3】:

      我不确定是否有直接命令,但您始终可以使用简单的循环和移位来获取变量中的结果。比如:

      @echo 关闭 设置 RESTVAR= 转移 :循环1 如果 "%1"=="" 转到 after_loop 设置 RESTVAR=%RESTVAR% %1 转移 转到循环1 :after_loop 回声%RESTVAR%

      如果有帮助请告诉我!

      【讨论】:

      • 是的,但你的回答是最完整的,也是我最终所做的。
      • 这个答案有一个小问题——RESTVAR 将包含一个前导空格。这是一个稍微好一点的版本stackoverflow.com/a/761658/1488656
      • 当参数包含 '=' 即 debug=1 变为 debug 1 时不起作用。
      • 好答案。但是声明有错误。当我将“%1”更改为“%~1”时它起作用了。
      【解决方案4】:

      有一个更短的解决方案(单行)利用for 循环的标记化功能:

      :: all_but_first.bat
      echo all: %*
      for /f "tokens=1,* delims= " %%a in ("%*") do set ALL_BUT_FIRST=%%b
      echo all but first: %ALL_BUT_FIRST%
      

      输出:

      > all_but_first.bat foo bar baz
      all: foo bar baz
      all but first: bar baz
      

      脚注:是的,此解决方案存在问题。几乎与使用批处理文件编写的任何内容相同。现在是 2021 年。使用 Powershell 或其他任何实际的脚本语言。

      【讨论】:

      • 对于 'all-but-n',将 tokens=1 替换为 tokens=n。其余参数仍将在%%b
      • 在某些情况下,您可能需要使用 !ALL_BUT_FIRST!而不是 %ALL_BUT_FIRST% (例如,如果您在其他循环中);见stackoverflow.com/questions/12423238/…
      • 如果您正在使用!var!,请不要忘记使用setlocal enabledelayedexpansion
      • 当引用的参数包含空格时不起作用,例如。 all_but_first.bat "first arg" "second arg"
      • 即使有空格也适用于我,将所有 =, 视为 arg 分隔符
      【解决方案5】:

      以下内容适用于带有 "=' ' 的 args(与 @MaxTruxa 答案相比)

      echo %*
      set _all=%*
      call set _tail=%%_all:*%2=%%
      set _tail=%2%_tail%
      echo %_tail%
      

      测试

      > get_tail.cmd "first 1" --flag="other options" --verbose
      "first 1" --flag="other options" --verbose
      --flag="other options" --verbose
      

      【讨论】:

      • 我真的想要一个 CALL SET 行的 ELI5 版本。
      • Advanced usage : CALLing internal commands。它的工作方式类似于setlocal EnableDelayedExpansion + set _tail=!_all:*%2=!
      • 这个会失败:get_tail.cmd -s -s arg1
      • 这对我来说是最好的解决方案,因为其他解决方案在参数中裁剪了我的逗号。
      • 看起来你正在对整个参数集进行第一个参数的字符串替换。这将失败,就像@RamanZhylich 所说,如果您的第一个参数恰好是任何后续参数的子字符串。这与@MaxTruxa 的回答一样糟糕,但几乎更糟糕,因为它并没有那么明显的错误。
      【解决方案6】:

      以下内容适用于带有“、=、''的 args。基于 Dmitry Sokolov 的回答。修复了第二个 arg 与第一个 arg 相同的问题。

      @echo off
      echo %*
      set _tail=%*
      call set _tail=%%_tail:*%1=%%
      echo %_tail%
      

      【讨论】:

      • 我认为这是唯一的故障安全答案,也是最简单的答案之一。它应该是被接受的。
      • 请解释这如何只替换字符串的 1 实例,因为字符串替换的替换部分以 * 开头,这使它很神奇:gist.github.com/binki/a96bbf9a282616671ecd7386a9f17510 ss64.com/nt/syntax-replace.html
      • 对我来说,%_tail% 有一个前导空格。
      • 不错,有前导空格(只知道它,应该不是问题),并且返回*= 没有参数,所以你最好检查它们是否不为空if not "%~1"=="" call set _tail=%%_tail:*%1=%%跨度>
      • 也将所有 =, 视为我的 arg 分隔符
      【解决方案7】:

      Sebi,这里是Syntax! 有一种行为,批量吃不双引号的等号,这会在上面的脚本中造成麻烦。如果你不想跳过,我已经根据 Raman Zhylich 答案和 strlen.cmd 进行了修改:

      @ECHO OFF
      SETLOCAL enableDelayedExpansion
      
      SET _tail=%*
      SET "_input="
      SET /A _len=0
      
      :again
      SET "_param=%1"
      SET "_input=%_input%%1"
      FOR /L %%i in (0,1,8191) DO IF "!_param:~%%i,1!"=="" (
          REM skip param
          SET /A _len+=%%i
          REM _len can't be use in substring
          FOR /L %%j in (!_len!,1,!_len!) DO (
              REM skip param separator
              SET /A _len+=1
              IF "!_tail:~%%j,1!"=="=" (SET "_input=%_input%=" & SHIFT & goto :again)
          )
      ) & goto :next
      :next
      IF %_len% NEQ 0 SET _tail=!_tail:~%_len%!
      
      ENDLOCAL & SET "_input=%_input%" & SET "_tail=%_tail%"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-11
        • 2012-07-23
        • 2018-05-05
        • 2013-07-30
        • 1970-01-01
        • 2017-01-22
        • 2017-12-31
        • 2015-12-14
        相关资源
        最近更新 更多