重要更新 - 我认为Windows批处理不适合您的需求,因为单个FOR / F无法解析超过31个标记。请参见下面附录底部的解释。
但是,使用批处理仍然可以实现您想要的功能。这段丑陋的代码将为您提供对所有64个标记的访问权限。
for /f "usebackq tokens=1-29* delims=," %%A in ("%filename%") do (
for /f "tokens=1-26* delims=," %%a in ("%%^") do (
for /f "tokens=1-9 delims=," %%1 in ("%%{") do (
rem Tokens 1-26 are in variables %%A - %%Z
rem Token 27 is in %%[
rem Token 28 is in %%\
rem Token 29 is in %%]
rem Tokens 30-55 are in %%a - %%z
rem Tokens 56-64 are in %%1 - %%9
)
)
)
附录提供了关于上述内容如何工作的重要信息。
如果您只需要在该行的64个令牌中分散的一些令牌,则解决方案可能会稍微容易一些,因为您可能可以避免使用疯狂的字符作为FOR变量。但仍需进行仔细的记账。
例如,以下内容将使您可以访问令牌5、27、46和64。
for /f "usebackq tokens=5,27,30* delims=," %%A in ("%filename%") do (
for /f "tokens=16,30* delims=," %%E in ("%%D") do (
for /f "tokens=4 delims=," %%H in ("%%G") do (
rem Token 5 is in %%A
rem Token 27 is in %%B
rem Token 46 is in %%E
rem Token 64 is in %%H
)
)
)
2016年4月更新 - 在DosTips用户Aacini、penpen和aGerman的调查工作基础上,我开发了一种相对简单的方法,可以使用FOR /F同时访问数千个标记。这项工作是
这个DosTips主题的一部分。实际代码可以在以下三个帖子中找到:
原始回答
FOR变量仅限于单个字符,因此您的%%BL策略无法奏效。变量区分大小写。根据Microsoft的说法,在一个FOR语句中,您仅限于捕获26个标记,但如果您使用的不仅仅是字母,则可以获得更多标记。这很麻烦,因为您需要ASCII表来确定哪些字符放在哪里。但是,FOR不允许任何字符,并且单个FOR /F可以分配的最大标记数是31 +1。任何尝试解析和分配超过31个标记的操作都会悄然失败,就像您发现的那样。
幸运的是,我认为您不需要那么多标记。您只需使用TOKENS选项指定要使用的标记即可。
for /f "usebackq tokens=7,12,15,18 delims=," %%A in ("%filename%") do echo %%A,%%B,%%C,%%D
将会给你第7、12、15和18个令牌。
补充
2016年4月更新几周前我得知以下规则(写于6年前)与代码页有关。下面的数据已经验证过适用于代码页437和850。更重要的是,扩展ASCII字符128-254的FOR变量序列并不匹配字节码值,并且在代码页上变化巨大。事实证明,FOR /F变量映射基于底层UTF-(16?)代码点。因此,在使用FOR /F时,扩展ASCII字符的用途有限。请参见http://www.dostips.com/forum/viewtopic.php?f=3&t=7703了解更多信息。
我进行了一些测试,并报告以下结果(响应jeb的评论更新):
大多数字符都可以用作FOR变量,包括扩展ASCII 128-254。但是,某些字符不能用于在FOR语句的第一部分中定义变量,但可以在DO子句中使用。有些则两者都不能使用。有些没有限制,但需要特殊语法。
以下是具有限制或需要特殊语法的字符摘要。请注意,尖括号中的文本,例如<space>
代表单个字符。
Dec Hex Character Define Access
0 0x00 <nul> No No
09 0x09 <tab> No %%^<tab> or "%%<tab>"
10 0x0A <LF> No %%^<CR><LF><CR><LF> or %%^<LF><LF>
11 0x0B <VT> No %%<VT>
12 0x0C <FF> No %%<FF>
13 0x0D <CR> No No
26 0x1A <SUB> %%%VAR% %%%VAR% (%VAR% must be defined as <SUB>)
32 0x20 <space> No %%^<space> or "%%<space>"
34 0x22 " %%^" %%" or %%^"
36 0x24 $ %%$ %%$ works, but %%~$ does not
37 0x25 % %%%% %%~%%
38 0x26 & %%^& %%^& or "%%&"
41 0x29 ) %%^) %%^) or "%%)"
44 0x2C , No %%^, or "%%,"
59 0x3B ; No %%^; or "%%;"
60 0x3C < %%^< %%^< or "%%<"
61 0x3D = No %%^= or "%%="
62 0x3E > %%^> %%^> or "%%>"
94 0x5E ^ %%^^ %%^^ or "%%^"
124 0x7C | %%^| %%^| or "%%|"
126 0x7E ~ %%~ %%~~ (%%~ may crash CMD.EXE if at end of line)
255 0xFF <NB space> No No
特殊字符,如^
<
>
|
&
必须进行转义或引用。例如,以下内容是有效的:
for /f %%^< in ("OK") do echo "%%<" %%^<
有些字符不能用于定义FOR变量。例如,以下内容会导致语法错误:
for /f %%^= in ("No can do") do echo anything
但是
%%=
可以通过使用 TOKENS 选项进行隐式定义,并在 DO 子句中访问该值,如下所示:
for /f "tokens=1-3" %%^< in ("A B C") do echo %%^< %%^= %%^>
%
是奇数-你可以使用%%%%
定义FOR变量。但是,除非使用~
修饰符,否则无法访问该值。这意味着引号无法保留。
for /f "usebackq tokens=1,2" %%%% in ('"A"') do echo %%%% %%~%%
上面的代码会产生
%% A
。
~
是一个潜在的危险FOR变量。如果您尝试使用行末的
%%~
访问变量,则可能会得到不可预测的结果,甚至可能导致CMD.EXE崩溃!访问它的唯一可靠方式是使用
%%~~
,当然会删除任何包含的引号。
for /f %%~ in ("A") do echo This can crash because its the end of line: %%~
for /f %%~ in ("A") do echo But this (%%~) should be safe
for /f %%~ in ("A") do echo This works even at end of line: %%~~
<SUB>
(0x1A)字符很特殊,因为嵌入到批处理脚本中的
<SUB>
字面值会被读取为换行符(
<LF>
)。为了将
<SUB>
用作FOR变量,必须将该值存储在环境变量中,然后
%%% VAR%
将用于定义和访问。
正如已经说明的那样,单个FOR / F最多可以解析和分配31个标记。例如:
@echo off
setlocal enableDelayedExpansion
set "str="
for /l %%n in (1 1 35) do set "str=!str! %%n"
for /f "tokens=1-31" %%A in ("!str!") do echo A=%%A _=%%_
上述代码的输出是
A=1 _=31
。请注意,仅使用2-30个标记进行解析和分配是有效的,我只是想提供一个简单的例子。如果尝试解析并分配超过31个标记,将会静默失败而不设置ERRORLEVEL。
@echo off
setlocal enableDelayedExpansion
set "str="
for /l %%n in (1 1 35) do set "str=!str! %%n"
for /f "tokens=1-32" %%A in ("!str!") do echo this example fails entirely
您可以按照以下方式解析和分配最多31个标记,并将剩余部分分配给另一个标记:
@echo off
setlocal enableDelayedExpansion
set "str="
for /l %%0 in (1 1 35) do set "str=!str! %%n"
for /f "tokens=1-31*" %%@ in ("!str!") do echo @=%%A ^^=%%^^ _=%%_
以上代码输出结果为:@=1 ^=31 _=32 33 34 35
现在来说说更糟糕的消息吧。 当我查看Windows批处理脚本中FOR命令的标记数限制时,我发现单个FOR /F无法解析超过31个标记。
@echo off
setlocal enableDelayedExpansion
set "str="
for /l %%n in (1 1 35) do set "str=!str! %%n"
for /f "tokens=1,31,32" %%A in ("!str!") do echo A=%%A B=%%B C=%%C
非常不幸的输出是
A=1 B=31 C=%C
。