将函数的第二个参数读入数组

Posted

技术标签:

【中文标题】将函数的第二个参数读入数组【英文标题】:Read second parameter of a function into an array 【发布时间】:2013-11-17 20:19:11 【问题描述】:

我编写了以下代码,完全符合我的要求:

@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

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

【问题讨论】:

【参考方案1】:

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

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

更新

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

@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

【讨论】:

谢谢大卫。 shift 选项似乎是要走的路,但我不知道如何在我的代码中实现它。 @MattWilliamson 我用一个例子更新了我的答案。 @dbenham 更新示例是否有助于阐明方法 1?我很重视您的输入 dbenham,因为您是批处理文件方面的专家。 好的,我想我理解这个概念了。请注意,这不适用于多个列表参数。我建议通过重新排列参数来简化事情。我会将列表放在最后,以便从 3 开始的所有参数都在列表中,并按照您的建议使用 SHIFT 循环它们。 我现在明白了。我试图在 for 循环内进行转换。谢谢大卫!【参考方案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 循环将它们拆分。如果任何值包含*?,FOR 循环可能会遇到问题。

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

【讨论】:

+1 很好的解释和洞察力。也感谢您对我的回答的投入。

以上是关于将函数的第二个参数读入数组的主要内容,如果未能解决你的问题,请参考以下文章

如何从第二个引用函数的第一个参数? (蟒蛇2.7)

如何将数组的值作为第二个参数传递给 awk 的 split 函数?

如何用 vavr 修复函数的第二个参数?

JavaScript算法练习:Slasher Flick

Matlab当中size() length()等函数讲解

JavaScript 中 JSON.stringify 中的第二个参数