为什么FOR / F设置为空值令牌中的其余部分重复的数字? [英] Why FOR /F sets empty values for repeated numbers in the rest of tokens?

查看:156
本文介绍了为什么FOR / F设置为空值令牌中的其余部分重复的数字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不知道这个问题是非常明显的因此这里有一个例子:

  :::此打印 -  1:[I] 2:[] 3:[] 4:[] 5:[] 6:[] 7:[]
FOR / F令牌= 1,1,1,1,1,1,1%%一中(I II III四五六七),做(
    @echo 1:%% A] 2:%% B] 3:[%% J] 4:%% D]。5:%% E] 6:%% F] 7:[%%摹]
):::此打印 - 1:[I] 2:[II] 3:[III] 4:[IV] 5:[] 6:[] 7:[%G]
FOR / F令牌= 2,3,1-4%%一中(I II III四五六七),做(
    @echo 1:%% A] 2:%% B] 3:[%% J] 4:%% D]。5:%% E] 6:%% F] 7:[%%摹]
):::此打印 - 1:[I] 2:[II] 3:[III] 4:[] 5:[] 6:[] 7:[%G]
FOR / F令牌= 1-3,1-3,%%一中(I II III四五六七),做(
    @echo 1:%% A] 2:%% B] 3:[%% J] 4:%% D]。5:%% E] 6:%% F] 7:[%%摹]

在短暂的如果有在标记列表中重复的数字(不要紧,如果他们是在像纳米的范围或由一个用逗号设置一个)相同数量的左访问令牌有空值。

无处这种行为被记录(或至少我没有发现这样的事情)。这里的帮助,涉及标记:

 标记= X,Y,M-N  - 指定每行令牌是
                  被传递到身体的每个迭代。
                  这会导致额外变量名称
                  进行分配。在M-N的形式是一个范围,
                  通过指定的第n个令牌第m个。如果
                  在令牌的最后一个字符=字符串是一个
                  星号,那么额外的变量
                  分配并接收在剩余的文本
                  最后一个令牌之后的行解析。

这是对Win8x64睾丸,所以我甚至不知道这会发生在Windows机器上的所有范围。

编辑:尽管入店令牌限于31这是我可以创造出更多的空标记:

  SETLOCAL disableDelayedExpansion
FOR / F令牌= 1-31,1-31,1-31%%!在(
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
)做(
 回音1: - 30 %%!]:[%% - ?] 31:%% @ - @] 32:[%% AA] 33:%% BB] 34:%% CC] 35 :[%% DD] 36:%% EE] 37:%% FF] 38:%% GG] 90:[{%% - {]

编辑。最大空令牌是250(不知道如何扩展ASCII字符将0X02和0xFB的才能与被显示):

 关闭@echo
FOR / F令牌= 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%%的(
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)做(
    回声0X02 - %% - 0×07 - %% - 0xFE的 - %%ю-0xFB的才能 - %%ы-0xFA回应 - %%ъ-


解决方案

虽然我为何命令的作用没有真正的想法是这样,有一些简单的匹配行为的规则。在这里,我们对标记子句才说话。 delims EOL 跳过有usebackq 其他日

第1步 - 记号子句中。该条款被解析,并为每个请求的范围(只有一个,启动结束, * ),如果它是有效的确定。如果它不是一个有效的请求(未在范围1-31或不 * )被丢弃,但如果它是一个有效的请求,对于每个元件所需的一个可变被分配(可能是一个表),以购买存储此令牌检索的数据。同时,一组被定义(也许一个位图掩模),设定该令牌数x(所使用的号码来标识在令牌标记子句)将被检索。同理,还可以要求几次,但在设置(或位掩码,...)的唯一作用是再次标记,该标记x将被检索。

现在的设置中包含有效的位置(1-31, * )的请求令牌。

一旦分析器结束处理配置后,输入文件readed到内存中,或执行命令来检索其所有输出到内存或字面字符串被声明为输入缓冲区。

第2步 - prepare行解析。的表来保存令牌数据被初始化为空白和设置为在表中的第一位置(第一令牌)的指针。如果线路没有被丢弃跳过 EOL 或者是因为它是空的,标记生成器会扫描输入缓冲区为令牌,否则,搜索行的末尾并重复步骤2中发现的新生产线。

第3步 - 解析输入缓冲区。直至达到行的末尾,在该行中找到的每个标记的位置,如果范围(1-31或 * 标记),对被检查设置,以确定是否已要求或没有它(如果此令牌数量是集合或者如果 * 令牌被处理)。如果已经要求,其数据包含在表?中的位置表示由表指针,递增指针和标记生成器将继续重复步骤3,直至到达该行的末尾

第四步 - 该行的末尾已到达。如果有任何令牌已检索或如果请求的唯一令牌 * (测试 FOR / F令牌= *一个以%表示()做回声%A )的不要子句中执行code。

第5步 - 如果的并没有被取消,并在缓冲区末尾还没有达到,还有更多的excution行处理,回到步骤2。

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

现在,让我们检查一下对code的问题

  :::此打印 -  1:[I] 2:[] 3:[] 4:[] 5:[] 6:[] 7:[]
FOR / F令牌= 1,1,1,1,1,1,1%%一中(I II III四五六七),做(
    @echo 1:%% A] 2:%% B] 3:[%% J] 4:%% D]。5:%% E] 6:%% F] 7:[%%摹]

7要求的标记,所以7头寸将被传递到不要 code中的表,但是相匹配的设置唯一的标记是1号

  :::此打印 -  1:[I] 2:[II] 3:[III] 4:[IV] 5:[] 6:[] 7:[% G]
FOR / F令牌= 2,3,1-4%%一中(I II III四五六七),做(
    @echo 1:%% A] 2:%% B] 3:[%% J] 4:%% D]。5:%% E] 6:%% F] 7:[%%摹]

6请求令牌,在令牌的表6的位置,和设置将只匹配-1,2,3,4-

  :::此打印 -  1:[I] 2:[II] 3:[III] 4:[] 5:[] 6:[] 7:[%G ]
FOR / F令牌= 1-3,1-3,%%一中(I II III四五六七),做(
    @echo 1:%% A] 2:%% B] 3:[%% J] 4:%% D]。5:%% E] 6:%% F] 7:[%%摹]

6请求令牌,在令牌的表6的位置,和设置将只匹配1,2,3

  SETLOCAL disableDelayedExpansion
FOR / F令牌= 1-31,1-31,1-31%%!在(
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
)做(
 回音1: - 30 %%!]:[%% - ?] 31:%% @ - @] 32:[%% AA] 33:%% BB] 34:%% CC] 35 :[%% DD] 36:%% EE] 37:%% FF] 38:%% GG] 90:[{%% - {]

93请求令牌,令牌中的分配表93的位置,在设置将只匹配元素1-31

编辑更多的情况下加入到这个问题。


  

最大空令牌是250


 关闭@echo
FOR / F令牌= 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%%的(
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)做(
    回声0X02 - %% - 0×07 - %% - 0xFE的 - %%ю-0xFB的才能 - %%ы-0xFA回应 - %%ъ-

没有,你可以要求尽可能多的标记,你可以。我1625 1-30 和aditional的31测试(以确保解析器继续工作),它是没有问题的处理。也许是限行lengh。您最多可以请求50530(近似)令牌(重复1-31,......到达极限线),但你只限于获取有效数据的31个第一令牌和空白数据在元素的其余部分存储表,不必检索使用在一个字符为替换参数元素。使用 %% ^ A (0×01,的Alt-001 )为替换参数,你最多可以请求 %%ÿ(0xFF的,的Alt-255

Not sure if the question is clear enough so here's an example:

:::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]
)

In brief if there's a repeated numbers in the list of tokens (doesn't matter if they are in the ranges like n-m or set one by one with commas ) the same number of the left accessed tokens have empty values.

Nowhere this behavior is documented (or at least I didn't found such thing).Here's FOR help that concerns tokens:

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.

This is testes on Win8x64 so I'm not even sure this will happen on all the range of Windows machines.

EDIT: Despite the accesible tokens are limited to 31 with this I can create more empty tokens :

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:[%%{-{] 
)

edit. the maximum of the empty tokens is 250 (not sure how the extended ascii characters will be displayed between 0x02 and 0xFB):

@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-%%ъ- 
)

解决方案

While i have no real idea of why the for command behaves as it does, there are some simple rules that match the for behaviour. And here we are talking only about the token clause. delims, eol, skip and usebackq other day

Step 1 - The tokens clause is found. The clause is parsed, and for each range requested (only one, start-end, *) it is determined if it is valid. It is discarded if it is not a valid request (not in the range 1-31 or not *) but if it is a valid request, for each element requested a "variable" is allocated (probably a table) to later hold the data retrieved for this token. At the same time, a "set" is defined (maybe a bitmap mask), setting that the token number x (the number used to identify the token in the tokens clause) will be retrieved. The same token can be requested several times, but in the "set" (or bitmask, ...) the only effect is to mark again that the token x will be retrieved.

Now the "set" contains the position of the valid (1-31, *) tokens that were requested.

Once after the parser ends to process the for configuration, the input file is readed into memory, or the command is executed to retrieve all its output into memory or the literal string is declared as the input buffer.

Step 2 - Prepare line parse. The table to hold the token data is initialized to blanks and a pointer set to the first position in the table (the first token). If the line has not been discarded by skip, eol or because it is empty, the tokenizer will scan the input buffer for tokens, else, search the end of the line and repeat step 2 for the new line found.

Step 3 - Parse the input buffer. Until the end of a line is reached, for each token found in the line its position, if in range (1-31 or * token), is checked against the "set" to determine if it has been requested or not (if this token number is in the set or if the * token is being handled). If it has been requested, its data is included in the "table"? in the position indicate by the table pointer, the pointer incremented and the tokenizer continues repeating step 3 until the end of the line is reached.

Step 4 - The end of the line has been reached. If any token has been retrieved or if the only token requested was * (test for /f "tokens=*" %a in (" ") do echo %a), execute the code in the do clause.

Step 5 - If the excution of the for has not been canceled and the end of the buffer has not been reached, there are more lines to process, back to step 2.

This set of steps reproduce all the observed behaviours in the question, but does not prove if this is the way the for command is coded.

Now, let's check it against the code in the question

:::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 requested tokens, so 7 positions in the table that will be passed to the do code, but the only token that matches the "set" is the number 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 requested tokens, 6 position in the table of tokens, and the "set" will only match 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 requested tokens, 6 positions in the table of tokens, and the "set" will only match 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 requested tokens, 93 positions allocated in the table of tokens, the "set" will only match elements 1-31

edited more cases added to the question

the maximum of the empty tokens is 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)

这篇关于为什么FOR / F设置为空值令牌中的其余部分重复的数字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆