为什么 FOR /F 将其余标记中的重复数字设置为空值?

2024-01-11

不确定问题是否足够清楚,所以这是一个例子:

:::this prints - 1:[i] 2:[] 3:[] 4:[] 5:[] 6:[] 7:[]
for /f "tokens=1,1,1,1,1,1,1" %%a in ("i ii iii iv v vi vii") do (
    @echo 1:[%%a] 2:[%%b] 3:[%%c] 4:[%%d] 5:[%%e] 6:[%%f] 7:[%%g]
)

:::this prints - 1:[i] 2:[ii] 3:[iii] 4:[iv] 5:[] 6:[] 7:[%g]
for /f "tokens=2,3,1-4" %%a in ("i ii iii iv v vi vii") do (
    @echo 1:[%%a] 2:[%%b] 3:[%%c] 4:[%%d] 5:[%%e] 6:[%%f] 7:[%%g]
)

:::this prints - 1:[i] 2:[ii] 3:[iii] 4:[] 5:[] 6:[] 7:[%g]
for /f "tokens=1-3,1-3," %%a in ("i ii iii iv v vi vii") do (
    @echo 1:[%%a] 2:[%%b] 3:[%%c] 4:[%%d] 5:[%%e] 6:[%%f] 7:[%%g]
)

简而言之,标记列表中是否有重复的数字(如果它们在以下范围内并不重要)n-m或用逗号一一设置)相同数量的左侧访问令牌具有空值。

这种行为没有记录在案(或者至少我没有发现这样的事情)。这里是FOR涉及代币的帮助:

tokens=x,y,m-n  - specifies which tokens from each line are to
                  be passed to the for body for each iteration.
                  This will cause additional variable names to
                  be allocated.  The m-n form is a range,
                  specifying the mth through the nth tokens.  If
                  the last character in the tokens= string is an
                  asterisk, then an additional variable is
                  allocated and receives the remaining text on
                  the line after the last token parsed.

这是 Win8x64 上的测试,所以我什至不确定这是否会发生在所有 Windows 机器上。

EDIT:尽管可访问的令牌仅限于 31 个,但我可以创建更多空令牌:

setlocal disableDelayedExpansion
for /f "tokens=1-31,1-31,1-31" %%! in (
"33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 "
) do (
 echo 1:[%%!-!]  30:[%%?-?] 31:[%%@-@] 32:[%%A-A] 33:[%%B-B] 34:[%%C-C] 35:[%%D-D] 36:[%%E-E] 37:[%%F-F] 38:[%%G-G] 90:[%%{-{] 
)

编辑。空标记的最大值为 250(不确定 0x02 和 0xFB 之间的扩展 ascii 字符将如何显示):

@echo off
for /f "tokens=1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31" %% in (
"1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1") do (
    echo 0x02-%%- 0x07-%%- 0xFE-%%ю-  0xFB-%%ы- 0xFA-%%ъ- 
)

虽然我不知道为什么for命令的行为就像它一样,有一些简单的规则与for行为。这里我们只讨论token条款。delims, eol, skip and usebackq另一天

Step 1- 找到标记子句。该子句被解析,并且对于每个请求的范围(只有一个,开始-结束,*) 判断是否有效。如果不是有效请求(不在1-31范围内或者不在范围内)则被丢弃*)但如果​​这是一个有效的请求,则为请求的每个元素分配一个“变量”(可能是一个表)以稍后保存为此令牌检索的数据。同时,定义一个“集合”(可能是位图掩码),设置令牌编号x(用于识别令牌中的令牌的编号)tokens子句)将被检索。可以多次请求相同的令牌,但在“set”(或位掩码,...)中,唯一的效果是再次标记将检索令牌 x。

现在“集合”包含有效的位置(1-31,*) 所请求的令牌。

一旦解析器结束处理for配置中,输入文件被读入内存,或者执行命令以将其所有输出检索到内存中,或者将文字字符串声明为输入缓冲区。

Step 2- 准备行解析。保存令牌数据的表被初始化为空白,并将指针设置为表中的第一个位置(第一个令牌)。如果该行未被丢弃skip, eol或者因为它是空的,标记生成器将扫描输入缓冲区中的标记,否则,搜索该行的末尾并重复步骤 2 以查找找到的新行。

Step 3- 解析输入缓冲区。直到到达行尾,对于在该行中找到的每个标记,如果其位置在范围内(1-31 或*令牌),根据“集合”进行检查以确定它是否已被请求(如果该令牌编号在集合中或者如果*令牌正在处理中)。如果已请求,其数据是否包含在“表”中?在表指针指示的位置,指针递增,分词器继续重复步骤 3,直到到达行尾。

Step 4- 已到达线路末端。如果已检索到任何令牌或者请求的唯一令牌是* (test for /f "tokens=*" %a in (" ") do echo %a),执行里面的代码do clause.

Step 5- 如果执行for尚未取消且尚未到达缓冲区末尾,还有更多行需要处理,返回步骤 2。

这组步骤重现了问题中所有观察到的行为,但并不能证明这是否是问题的方式for命令已编码。

现在,让我们对照问题中的代码进行检查

:::this prints - 1:[i] 2:[] 3:[] 4:[] 5:[] 6:[] 7:[]
for /f "tokens=1,1,1,1,1,1,1" %%a in ("i ii iii iv v vi vii") do (
    @echo 1:[%%a] 2:[%%b] 3:[%%c] 4:[%%d] 5:[%%e] 6:[%%f] 7:[%%g]
)

7 个请求的令牌,因此表中的 7 个位置将传递给do代码,但与“set”匹配的唯一标记是数字 1

:::this prints - 1:[i] 2:[ii] 3:[iii] 4:[iv] 5:[] 6:[] 7:[%g]
for /f "tokens=2,3,1-4" %%a in ("i ii iii iv v vi vii") do (
    @echo 1:[%%a] 2:[%%b] 3:[%%c] 4:[%%d] 5:[%%e] 6:[%%f] 7:[%%g]
)

6个请求的token,在token表中的6个位置,“set”只会匹配1,2,3,4

:::this prints - 1:[i] 2:[ii] 3:[iii] 4:[] 5:[] 6:[] 7:[%g]
for /f "tokens=1-3,1-3," %%a in ("i ii iii iv v vi vii") do (
    @echo 1:[%%a] 2:[%%b] 3:[%%c] 4:[%%d] 5:[%%e] 6:[%%f] 7:[%%g]
)

6个请求的token,在token表中的6个位置,“set”只会匹配1,2,3

setlocal disableDelayedExpansion
for /f "tokens=1-31,1-31,1-31" %%! in (
"33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 "
) do (
 echo 1:[%%!-!]  30:[%%?-?] 31:[%%@-@] 32:[%%A-A] 33:[%%B-B] 34:[%%C-C] 35:[%%D-D] 36:[%%E-E] 37:[%%F-F] 38:[%%G-G] 90:[%%{-{] 
)

93 个请求的令牌,令牌表中分配的 93 个位置,“集合”仅匹配元素 1-31

edited问题中添加了更多案例

空令牌的最大数量为 250

@echo off
for /f "tokens=1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31,1-31" %% in (
"1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1") do (
    echo 0x02-%%- 0x07-%%- 0xFE-%%ю-  0xFB-%%ы- 0xFA-%%ъ- 
)

No, you can request as much tokens as you can. I tested with 1625 1-30 and an aditional 31 (to ensure the parser keeps working), and it is handled without problems. Probably the limit is the line lengh. You can request up to 50530 (aprox) tokens (repeating 1-31,... to reach the line limit), but you are limited to get valid data for the 31 first tokens and blank data for the rest of the elements in the storage table, having to retrieve elements using a single character in the for replaceable parameter. Using %%^A (0x01, Alt-001) as the for replaceable parameter, you can request up to %%ÿ (0xFF, Alt-255)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 FOR /F 将其余标记中的重复数字设置为空值? 的相关文章

随机推荐