【问题标题】:for /F not working as expected, not giving every elementfor /F 没有按预期工作,没有给出每个元素
【发布时间】:2023-01-18 21:15:25
【问题描述】:

我有一个简单的 .bat 内容:

@echo off

set "var=VAR1?VAR2?VAR3"
echo.%var%
echo.
for /F "delims=?" %%H in ('echo.%var%') do echo.%%~H

我希望得到以下输出:

VAR1?VAR2?VAR3

VAR1
VAR2
VAR3

相反,我得到:

VAR1?VAR2?VAR3

VAR1

^ 注意一个尾随的空新行

尝试使用不同的定界符,usebackq,赋予 eol 字符,运行另一个具有不同参数的 for 循环,还有许多其他事情;不同的变量名,不同的文件名,setlocal w/o 和 w/ delayed expansion;没有成功。 如果我包含 tokens=1,2 参数,它会将 VAR1 打印到 %%H 中,将 VAR2 打印到 %%I 中,但我需要它是“动态的”,为我的 %var% 提供每个元素。

编辑:最让我困惑的是,如果不是将我的元素写入一个由 a 分隔的变量,我把它写到一个文件中,每个元素在它自己的行中,然后用 "for /F "delims=*" %%H in ('type "VAR.txt"') 逐行读取文件。 ..” 它工作完美。是因为“delims=*”,还是有更高的权力在搞乱我?从 FOR 的角度来看,我看不出有什么不同。如果默认情况下它应该只给我第一个标记,为什么它会给出文件中的每个标记?作为新行的标记是否与作为任何其他字符的标记相同?

【问题讨论】:

  • 您只要求默认(第一个分隔标记,%%H)。如果您想要每个令牌,您将需要知道有多少个令牌,或者以不同的方式执行任务。例如:For %%G In (%var:?=,%) Do Echo %%G
  • 使用双引号设置变量,即set "var="VAR1" "VAR2" "VAR3"",然后只需使用for %%H in (%var%) do echo %%~H,这样,您也可以使用空格,即set "var="VAR 1" "VAR 2" "VAR 3""
  • 可悲的是,我必须在我的元素之间使用不能出现在文件名中的定界符,所以像 [space]#+%= 和其他的东西是不可能的。
  • 那么你只有一个选择,计算分隔字符的数量,然后动态设置标记。

标签: for-loop batch-file cmd token


【解决方案1】:

for/f 读取的每一行都被分成“令牌”,子字符串由任何定界符分隔。

默认情况下,tokens=1,因此仅将行中的第一个标记分配给元变量%%H

您可以在 tokens= 子句中列出每个必需的标记。

要依次将每个分配给%%H,请尝试

for %%H in (%var:?= %) do echo %%H

或者如果您的元素包含空格,

for %%H in ("%var:?=" "%") do echo.%%~H

“额外”的换行符是一条红鲱鱼。你误读了结果。

【讨论】:

  • 它在这种情况下有效,遗憾的是,如果元素本身包含空格,它就会中断,这就是我选择问号的原因。不错的主意!为什么我不明白这整件事是因为如果我用 TYPE 逐行遍历一个文件,它会完美地工作: for /F "delims=*" %%A in ('type "my file.txt" ')... 如果 delim 是换行而不是一个字符,它实际上是不同的吗?
  • 和问号以消除在我的元素中使用 # 之类的文件名的可能性。 Windows 禁止问号,所以它不能出现在元素中存储的文件名中。
【解决方案2】:

这是一种可能的替代方法,只要每个问号分隔的标记不包含双引号或感叹号字符,就应该没问题:

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion

Rem Dehine a variable named var.
Set "var=VAR 1?VAR,2?VAR|3?VAR;4?VAR<5?VAR>6?VAR&7?VAR=8"

Rem view the content of the variable named var.
Set /P "=%var%" 0<NUL & Echo(

Rem Display an optional empty line
Echo(

Rem Undefine and variables beginning with the string var[.
For /F "Delims==" %%G In ('"(Set var[) 2>NUL"') Do Set "%%G="

Rem define a increment counter
Set "i=1"

Rem Enable delayed variable expansion
SetLocal EnableDelayedExpansion

Rem Define variables named var[increment] splitting var at each question mark.
Set "var[%i%]=%var:?=" & Set /A i +=1 & Set "var[!i!]=%"

Rem Disable delayed variable expansion
Rem  and display the individual incremented variable values.
For /F "Tokens=1-2,* Delims=[]=" %%G In ('"(Set var[) 2>NUL"') Do (EndLocal
    Set /P "=%%I" 0<NUL & Echo()

Rem Display an optional empty line
Echo(

Pause

请注意,如果有超过九个标记,显示顺序当前将与初始变量中的顺序不匹配。为此必须做出调整。


预期输出:

VAR 1?VAR,2?VAR|3?VAR;4?VAR<5?VAR>6?VAR&7?VAR=8

VAR 1
VAR,2
VAR|3
VAR;4
VAR<5
VAR>6
VAR&7
VAR=8


Press any key to continue . . .

【讨论】:

  • 现在这看起来像是真正的黑魔法!尽管除了打印变量我不知道该怎么做。将它保存到不同的文件,然后我猜 CALLing 应该可以工作,对吧?
  • 我已经回答了你的问题,即从一个由问号分隔的变量开始,并以与你在问题中显示的完全相同的方式显示它们。如果你想要别的东西,你应该直接要求。
猜你喜欢
  • 1970-01-01
  • 2016-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-22
  • 2018-11-01
  • 2017-12-10
相关资源
最近更新 更多