2

我编写了以下代码,它完全按照我想要的方式工作:

@echo off
setlocal enabledelayedexpansion

set /a i=0
set in="This is line 1", "This is line 2"
for %%h in (%in%) do (
   set /a i+=1
   set "val[!i!]=%%h"
)
set out=
for /l %%n in (1,1,!i!) do (
  set out=!out! !val[%%n]! ^& vbcrlf ^& _)
echo !out:~1,-12!

它获取 %in% 变量的值并将每个逗号分隔的行读入数组的一个元素,然后对其进行一些字符串连接并吐出一个新字符串。现在,当我尝试将其转换为函数时,它失败了,因为 %2 被解析为参数。我需要将 %2 解析为具有可变数量值的单个逗号分隔字符串。这个简单的测试不起作用:

call :Test Title "This is line 1","This is line 2" "arg3"
exit /b

:Test arg1 arg2 arg3
set /a i=0
for %%h in (%2) do (
   set /a i+=1
   set "val[!i!]=%%h"
)
set out=
for /l %%n in (1,1,!i!) do (
  set out=!out! !val[%%n]! ^& vbcrlf ^& _)
echo %1 !out:~1,-12! %3
exit /b

我唯一能想到的就是使用 %* 并将分隔符更改为独特的东西,但如果可能的话,我宁愿避免这种情况。

4

2 回答 2

3

1.通过中间参数移位

这将不理会%1并转移所有中间参数,当没有更多参数时停止并将最后一个参数留在%3.

@echo off
setlocal
call :Test One "Two","Three" Four
endlocal
exit /b 0

:Test <Title> <Lines...> <LastArg>
echo %2
set "Temp=%4"
if defined Temp shift /2 & goto Test
echo %1
echo %3
exit /b 0

输出

"Two"
"Three"
One
Four

2.将字符串放入变量中,并传递变量名

@echo off
setlocal EnableDelayedExpansion
set "String="Two","Three""
call :Test One String Four
endlocal
exit /b 0

:Test <a> <b> <c>
echo %1
echo !%2!
echo %3
exit /b 0

输出

One
"Two","Three"
Four

这是我想到的前两个解决方案。

更新

这是使用内部循环应用于您的代码的 shift 方法:__Test

@echo off
setlocal EnableDelayedExpansion
call :Test Title "This is line 1","This is line 2" "arg3"
endlocal
exit /b 0

:Test <arg1> <arg2[,...]> <arg3>
set "i=0"
:__Test
set /a "i+=1"
set "val[!i!]=%2"
set "tempvar=%4"
if defined tempvar shift /2 & goto __Test
set "out="
for /l %%n in (1,1,!i!) do (
  set out=!out! !val[%%n]! ^& vbcrlf ^& _)
echo %1 !out:~1,-12! %3
exit /b 0
于 2013-11-06T14:49:57.217 回答
2

对于一般解决方案,通过引用传递值(将值存储在变量中并传递变量名称)是最佳选择。这与 David Ruhmann 的第二个选项相同。

还有另一种方法,但它需要调用者做更多的工作。您可以要求将参数值中的所有引号加倍,然后将整个参数括在另一组引号中。在函数中,全部替换"""以获得所需的值。我曾经使用这种方法,直到我了解了通过引用传递值。

@echo off
setlocal enableDelayedExpansion
call :Test Title """This is line 1"",""This is line 2""" "arg3"
exit /b

:Test arg1 arg2 arg3
set "arg2=%~2"
set "arg2=%arg2:""="%"
echo arg1=%1
echo arg2=%arg2%
echo arg3=%3

更新

通过引用传递值是传递包含标记分隔符和引号的复杂值的最佳选择。

但是 OP 对作为单个参数的值列表并不真正感兴趣,因为使用 FOR 循环将它们拆分。*如果任何值包含or , FOR 循环可能会遇到麻烦?

我现在看到,对于这种特殊情况,最好将列表移动到末尾,这样从 3 开始的所有参数都是列表的一部分。然后使用SHIFT /3GOTO循环读取列表值。这基本上是大卫鲁曼的选项 1。

于 2013-11-06T17:02:21.003 回答