1

我需要一种快速的方法来在 bat 文件中插入几行结构化数据我使用了一个名为 myarray 的数组来扫描和“读取”我的值,但它不起作用,我不明白为什么这是我的代码:

@echo off
set myarray[1]=myfield1#myfield2#mysubfield31;mysubfield32#myfield4
for /f "tokens=1-9 delims=#" %%a in ('echo %myarray[1]%') do (
    echo field1 is %%a
    echo field2 is %%b
    echo field3 is %%c
    echo field4 is %%d
    for /f "tokens=1-9 delims=;" %%k in ('echo %%c') do (
        echo subfield3 is %%k
        echo subfield3 is %%l       
    )
)

输出是这样的:

field1 is myfield1
field2 is myfield2
field3 is mysubfield31 mysubfield32
field4 is myfield4
subfield3 is mysubfield31 mysubfield32
subfield3 is

为什么我不能简单地获得:

subfield3 is mysubfield31 
subfield3 is mysubfield32

哪儿是 ”;” 在第二个中用作分隔符?

4

3 回答 3

5

这有效:

@echo off
set myarray[1]=myfield1#myfield2#mysubfield31;mysubfield32#myfield4
for /f "tokens=1-9 delims=#" %%a in ("%myarray[1]%") do (
    echo field1 is %%a
    echo field2 is %%b
    echo field3 is %%c
    echo field4 is %%d
    for /f "tokens=1-9 delims=;" %%k in ("%%c") do (
        echo subfield3 is %%k
        echo subfield3 is %%l       
    )
)
pause
于 2013-06-30T15:38:28.697 回答
1
for /f "tokens=1-9 delims=#" %%a in ("%myarray[1]%") do (

可能会更好一点...

于 2013-06-30T14:56:42.277 回答
-1

这是记录在案的行为,分号被视为空格(不是由for循环,而是由执行echo命令的子shell)。这会导致分号被替换为空格,从而echo field3 is %%c产生输出field3 is mysubfield31 mysubfield32。从内部循环中删除delims=;,因此它使用默认分隔符(空格和制表符),或者选择不同的分隔符,您的脚本应该按预期工作。但是请注意,当嵌套“数组”的字段包含空格时,依赖内部循环中的默认分隔符可能会产生不希望的结果。

证明:

  1. 根本原因的证明:

    for /f "tokens=*" %%a in ('echo.a#b;c#d^|find ";"') do echo _%%a_
    

    输出:无(即在回显的字符串中找不到分号)

    for /f "tokens=*" %%a in ('echo.a#b;c#d^|find " "') do echo _%%a_
    

    输出:_a#b c#d_

    显然这适用于所有分隔符,, ;, =, 空格和制表符),因为我可以用它们中的每一个来重现这种行为。

  2. 带有输入字符串的简化脚本a#b;c#d

    @echo off
    set "foo=a#b;c#d"
    for /f "tokens=1-3 delims=#" %%a in ('echo %foo%') do (
      echo field1 is %%a
      echo field2 is %%b
      echo field3 is %%c
      for /f "tokens=1-2 delims=;" %%k in ('echo %%b') do (
        echo subfield3 is %%k
        echo subfield3 is %%l       
      )
    )
    

    输出:

    field1 is a
    field2 is b c
    field3 is d
    subfield3 is b c
    subfield3 is

    注意输出的第2b和第4之间的空格。c

  3. 与 2. 相同的脚本,但delims=;已从内部循环中删除:

    @echo off
    set "foo=a#b;c#d"
    for /f "tokens=1-3 delims=#" %%a in ('echo %foo%') do (
      echo field1 is %%a
      echo field2 is %%b
      echo field3 is %%c
      for /f "tokens=1-2" %%k in ('echo %%b') do (
        echo subfield3 is %%k
        echo subfield3 is %%l       
      )
    )
    

    输出:

    field1 is a
    field2 is b c
    field3 is d
    subfield3 is b
    subfield3 is c

    请注意,嵌套的“数组” b;c(来自变量%foo%)现在被处理为正确的输出(第 4 行和第 5 行)。这是因为空格和制表符是for /f循环中的默认分隔符。

  4. 与 2. 相同的脚本,但+用作嵌套“数组”的分隔符:

    @echo off
    set "foo=a#b+c#d"
    for /f "tokens=1-3 delims=#" %%a in ('echo %foo%') do (
      echo field1 is %%a
      echo field2 is %%b
      echo field3 is %%c
      for /f "tokens=1-2 delims=+" %%k in ('echo %%b') do (
        echo subfield3 is %%k
        echo subfield3 is %%l       
      )
    )
    

    输出:

    field1 is a
    field2 is b+c
    field3 is d
    subfield3 is b
    subfield3 is c

    请注意,第二个输出行不再包含虚假空间,并且嵌套的“数组”再次被正确处理(第 4 行和第 5 行)。


为了完整性:更好的解决方案是完全放弃echo并简单地在双引号字符串上循环,正如foxidrivePeter Wright所建议的那样,因为它完全避免了这个问题。

@echo off
set "foo=a#b;c#d"
for /f "tokens=1-3 delims=#" %%a in ("%foo%") do (
  echo field1 is %%a
  echo field2 is %%b
  echo field3 is %%c
  for /f "tokens=1-2 delims=;" %%k in ("%%b") do (
    echo subfield3 is %%k
    echo subfield3 is %%l       
  )
)

dbenham 提出的另一个解决方案是启用延迟扩展并在运行时扩展变量:

@echo off
setlocal EnableDelayedExpansion
set "foo=a#b;c#d"
for /f "tokens=1-3 delims=#" %%a in ('echo !foo!') do (
  echo field1 is %%a
  echo field2 is %%b
  echo field3 is %%c
  for /f "tokens=1-2 delims=;" %%k in ('echo %%b') do (
    echo subfield3 is %%k
    echo subfield3 is %%l       
  )
)

然而,更好的解决方案是完全放弃批处理并切换到实际支持数组的语言,例如 PowerShell。

于 2013-06-30T14:23:47.327 回答