Board logo

标题: [文本处理] 批处理使用for循环获取命令行参数,shift之后不能改变%1的值? [打印本页]

作者: icbc    时间: 2017-3-26 07:29     标题: 批处理使用for循环获取命令行参数,shift之后不能改变%1的值?

代码如下:
  1. @echo off
  2. rem testargs.bat
  3. rem useage: testargs.bat 3 2 1
  4. setlocal enabledelayedexpansion
  5. for /l %%i in (1,1,3) do (
  6. set arg=%1
  7. echo arg%%i:  !arg!
  8. shift
  9. )
复制代码
将以下代码保存为testargs.bat
运行 testargs.at 3 2 1之后发现,shift之后 %1的值不能改变,显示如下:
3
3
3
作者: Nsqs    时间: 2017-3-26 09:14

  1. @echo off
  2. set x=3
  3. call:a 3 2 1
  4. pause
  5. goto :eof
  6. :a
  7. echo %1
  8. shift
  9. set /a x-=1
  10. if %x% equ 0 goto :eof
  11. goto a
复制代码
因为在for中shift无法发挥作用
作者: icbc    时间: 2017-3-26 09:35

本帖最后由 icbc 于 2017-3-26 09:50 编辑

shift在for循环中已经发挥作用。如果不信,您可以在for循环前和循环后,分别 echo %1 %2 %3, 发现其值不一样。
  1. @echo off
  2. rem testargs.bat
  3. rem useage: testargs.bat 3 2 1
  4. setlocal enabledelayedexpansion
  5. echo %1 %2 %3
  6. for /l %%i in (1,1,3) do (
  7. set arg=%1
  8. echo arg%%i:  !arg!
  9. shift
  10. )
  11. echo %1 %2 %3
复制代码

作者: 0000    时间: 2017-3-26 11:56

回复 1# icbc


    第6行"%1"在预处理时已被替换
作者: icbc    时间: 2017-3-26 12:17

但已经声明了setlocal enabledelayedexpansion,可保证%1变量延迟处理
作者: /zhqsystem/zhq    时间: 2017-3-26 22:09

  1. for /l %%i in (1,1,3) do call echo,%%1&&shift
复制代码

%1不能写为!1,延迟就是无效,%1不属于变量,属于参数但是支持CALL传参
作者: icbc    时间: 2017-3-27 12:11     标题: 让人欢喜的循环变量%%i变成废物了,不起作用了,该怎么办?

各位哥哥、姐姐:您好!
  请帮我一把,我实在是无能为力了,昨天写了一个简单的获取命令参数的程序,老是显示第一个参数a,而不显示其它参数(b,c),变成了废物,各位高手也调诫不出来,代码如下:
  1. @echo off
  2. rem useage: testargs.bat a b c
  3. setlocal enabledelayedexpansion
  4. for /l %%i in (1,1,3) do (
  5.   echo %1
  6.   shift
  7. )
复制代码
运行结果如下:
a
a
a

今天,按照各位高手的教导改进了一下,可是%%i变成了废物,只运行了一次,就完蛋了!代码如下:
  1. @echo off
  2. rem testargs.bat
  3. rem useage: testargs.bat a b c
  4. setlocal enabledelayedexpansion
  5. set/a count=0
  6. for /l %%i in (1,1,3) do (
  7.   echo "%%i is :" %%i
  8.   goto y:
  9.   
  10. :x
  11.   echo %%i
  12.   shift
  13.   goto :y
  14. )
  15. :y
  16.   set/a count+=1
  17.   echo "arg%count% is :" %1
  18.   if %count%==3 goto :eof
  19.   goto :x
复制代码
运行结果如下:
"1 is :" 1
"arg1 is :" a
%i
"arg2 is :" b
%i
"arg3 is :" c
恳请各位哥哥姐姐伸手救助小弟一把,该死的batch编程太难了!
作者: ShowCode    时间: 2017-3-27 12:35

不知道哪个高手给你出的主意,第二个代码是错误的,不要在for循环内部定义标签然后尝试去跳转。
作者: Nsqs    时间: 2017-3-27 12:38

你这样写当然不行,变量i已经被goto跳出了,而且不应该使用goto,多善用call来跳转可提高程序可读性
作者: ShowCode    时间: 2017-3-27 12:38

  1. @echo off
  2. rem useage: testargs.bat a b c
  3. :loop
  4. if "%1" neq "" (
  5.     echo %1
  6.     shift
  7.     goto loop
  8. )
  9. pause
复制代码

作者: icbc    时间: 2017-3-27 13:00

回复 10# ShowCode
坚持用for循环实现,因为for循环的效率比较高,如果用for循环实现命令参数的遍历,该如何实现,请不要用for %%i in (%*),以及使用loop和goto。
请高手用for /l %%i in (1,1,3)给我写一看一看!,参照第一段代码的形式!
作者: ShowCode    时间: 2017-3-27 13:04

回复 11# icbc


    你的脚本写死了固定只接收3个参数,所以可以使用 for /l %%i in (1,1,3) 是这个意思吗?
作者: icbc    时间: 2017-3-27 13:08

回复 12# ShowCode
是的,请高手指教,我是偏执狂。
作者: ShowCode    时间: 2017-3-27 21:59

不知道你因为什么原因必须使用 for /l + shift
正如4楼所说,%1的扩展优先级较高,你启用变量延迟扩展对 !xxx! 这种类型的变量有效,对 %1 是无效的。
作者: ShowCode    时间: 2017-3-27 22:04

  1. @echo off
  2. for /l %%i in (1,1,3) do (
  3.     call echo arg%%i: %%1
  4.     shift
  5. )
复制代码
6楼给出的 call 方案有什么地方不满足需求吗?
作者: terse    时间: 2017-3-28 17:09

  1. call set str=%%1
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2