用于解析CSV文件并输出文本文件的Windows批处理脚本

时间:2021-08-06 02:22:31

I've seen a response on another page (Help in writing a batch script to parse CSV file and output a text file) - brilliant code BTW:

我在另一个页面上看到了一个响应(帮助编写一个批次脚本来解析CSV文件并输出一个文本文件)——出色的代码顺便说一句:

@ECHO OFFIF "%~1"=="" GOTO :EOFSET "filename=%~1"SET fcount=0SET linenum=0FOR /F "usebackq tokens=1-10 delims=," %%a IN ("%filename%") DO ^CALL :process "%%a" "%%b" "%%c" "%%d" "%%e" "%%f" "%%g" "%%h" "%%i" "%%j"GOTO :EOF:trimSET "tmp=%~1":trimleadIF NOT "%tmp:~0,1%"==" " GOTO :EOFSET "tmp=%tmp:~1%"GOTO trimlead:processSET /A linenum+=1IF "%linenum%"=="1" GOTO picknamesSET ind=0:displayIF "%fcount%"=="%ind%" (ECHO.&GOTO :EOF)SET /A ind+=1CALL :trim %1SETLOCAL ENABLEDELAYEDEXPANSIONECHO !f%ind%!!tmp!ENDLOCALSHIFTGOTO display:picknamesIF %1=="" GOTO :EOFCALL :trim %1SET /a fcount+=1SET "f%fcount%=%tmp%"SHIFTGOTO picknames

It works brilliantly for an example csv file I made in the format:

它非常适合我用这种格式制作的csv文件示例:

Header,Name,Placeone,two,threefour,five,six

However the actual file I want to change comprises of 64 fields - so I altered the tokens=1-10 to tokens=1-64 and increased the %%a etc right up to 64 variables (the last being called %%BL for example). Now, however, when I run the batch on my 'big' csv file (with the 64 tokens) nothing happens. No errors (good) but no output! (bad). If anyone can help that would be fantastic... am soooo close to getting the whole app working if I can just nail this last bit! Or if anyone has some example code that will do similar for an indefinite number of tokens... Ultimately I want to make a string which will be something like:

然而,我想要更改的实际文件包含64个字段——因此我将令牌=1-10改为令牌=1-64,并将%a等增加到64个变量(最后一个被称为%%BL)。然而,现在,当我在我的“大”csv文件(带有64个令牌)上运行批时,什么也没有发生。没有错误(很好),但是没有输出!(坏的)。如果有人能帮忙,那就太棒了……如果我能搞定最后一点,我就能让整个应用程序正常工作了!或者,如果有人有一些示例代码,这些代码会对不定数量的令牌进行类似的操作……最后,我想做一个字符串,大概是这样的:

field7,field12,field15,field18

4 个解决方案

#1


15  

Important update - I don't think Windows batch is a good option for your needs because a single FOR /F cannot parse more than 31 tokens. See the bottom of the Addendum below for an explanation.

重要的更新——我不认为Windows批处理对您的需求是一个好的选择,因为单个for /F不能解析31个令牌。有关解释,请参阅下面附录的底部。

However, it is possible to do what you want with batch. This ugly code will give you access to all 64 tokens.

但是,可以使用批处理来完成您想要的操作。这个难看的代码将使您能够访问所有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    )  ))

The addendum provides important info on how the above works.

附录提供了关于上述工作原理的重要信息。

If you only need a few of the tokens spread out amongst the 64 on the line, then the solution is marginally easier in that you might be able to avoid using crazy characters as FOR variables. But there is still careful bookkeeping to be done.

如果您只需要在队列中的64个标记中展开一些标记,那么解决方案就稍微容易一些,因为您可能可以避免使用疯狂字符作为变量。但仍有一些谨慎的簿记工作要做。

For example, the following will give you access to tokens 5, 27, 46 and 64

例如,下面将提供对令牌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    )  ))

April 2016 Update - Based on investigative work by DosTips users Aacini, penpen, and aGerman, I have developed a relatively easy method to simultaneously access thousands of tokens using FOR /F. The work is part of this DosTips thread. The actual code can be found in these 3 posts:

2016年4月更新——基于DosTips用户Aacini、penpen和aGerman的调查工作,我开发了一种相对简单的方法,可以同时使用FOR /F访问数千个令牌。这项工作是这个DosTips线程的一部分。实际代码可以在这3篇文章中找到:

Original AnswerFOR variables are limited to a single character, so your %%BL strategy can't work. The variables are case sensitive. According to Microsoft you are limited to capturing 26 tokens within one FOR statement, but it is possible to get more if you use more than just alpha. Its a pain because you need an ASCII table to figure out which characters go where. FOR does not allow just any character however, and the maximum number of tokens that a single FOR /F can assign is 31 +1. Any attempt to parse and assign more than 31 will quietly fail, as you have discovered.

变量的原始答案仅限于单个字符,因此您的%BL策略不能工作。变量是区分大小写的。根据微软的规定,你只能在一条语句中捕获26个令牌,但如果你使用的不仅仅是alpha,你可能会得到更多。这很麻烦,因为您需要一个ASCII表来确定哪些字符可以移动到哪里。然而,FOR不允许只允许任何字符,而且单FOR /F可以分配的令牌的最大数量是31 +1。任何解析和分配超过31个的尝试都会悄无声息地失败,正如您所发现的。

Thankfully, I don't think you need that many tokens. You simply specify which tokens you want with the TOKENS option.

谢天谢地,我想你不需要那么多代币。您只需使用令牌选项指定需要的令牌。

for /f "usebackq tokens=7,12,15,18 delims=," %%A in ("%filename%") do echo %%A,%%B,%%C,%%D

will give you your 7th, 12th, 15th and 18th tokens.

会给你第7、12、15和18个代币。

Addendum

齿顶高

April 2016 Update A couple weeks ago I learned that the following rules (written 6 years ago) are code page dependent. The data below has been verified for code pages 437 and 850. More importantly, the FOR variable sequence of extended ASCII characters 128-254 does not match the byte code value, and varies tremendously by code page. It turns out the FOR /F variable mapping is based on the underlying UTF-(16?) code point. So the extended ASCII characters are of limited use when used with FOR /F. See the thread at http://www.dostips.com/forum/viewtopic.php?f=3&t=7703 for more information.

2016年4月更新几周前,我了解到以下规则(6年前编写)是依赖于代码页的。下面的数据已经验证了代码页437和850。更重要的是,对于扩展ASCII字符128-254的变量序列与字节码值不匹配,且代码页差异很大。结果证明FOR /F变量映射基于底层的UTF-(16?)代码点。因此扩展的ASCII字符在与FOR /F使用时是有限的。请参阅http://www.doets com/forum/viewtopic.php?f = 3科技= 7703的更多信息。

I performed some tests, and can report the following (updated in response to jeb's comment):

我做了一些测试,可以报告如下(针对jeb的评论更新):

Most characters can be used as a FOR variable, including extended ASCII 128-254. But some characters cannot be used to define a variable in the first part of a FOR statement, but can be used in the DO clause. A few can't be used for either. Some have no restrictions, but require special syntax.

大多数字符都可以用作变量,包括扩展的ASCII 128-254。但是有些字符不能用于在FOR语句的第一部分中定义变量,但是可以在DO子句中使用。有几个都不能用。有些没有限制,但需要特殊的语法。

The following is a summary of characters that have restrictions or require special syntax. Note that text within angle brackets like <space> represents a single character.

下面是具有限制或需要特殊语法的字符的摘要。注意,像 这样的尖括号内的文本表示一个字符。

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

Special characters like ^ < > | & must be either escaped or quoted. For example, the following works:

等特殊字符^ < > | &必须逃跑或引用。例如,以下作品:

for /f %%^< in ("OK") do echo "%%<" %%^<

Some characters cannot be used to define a FOR variable. For example, the following gives a syntax error:

有些字符不能用于定义变量a。例如,下面给出一个语法错误:

for /f %%^= in ("No can do") do echo anything

But %%= can be implicitly defined by using the TOKENS option, and the value accessed in the DO clause like so:

但是%%=可以通过使用令牌选项隐式定义,并且DO子句中访问的值如下所示:

for /f "tokens=1-3" %%^< in ("A B C") do echo %%^< %%^= %%^>

The % is odd - You can define a FOR variable using %%%%. But The value cannot be accessed unless you use the ~ modifier. This means enclosing quotes cannot be preserved.

%是奇数-可以使用%%%% %为变量定义a。但是,除非使用~修饰符,否则无法访问该值。这意味着引号不能被保留。

for /f "usebackq tokens=1,2" %%%% in ('"A"') do echo %%%% %%~%%

The above yields %% A

上述收益率为% A

The ~ is a potentially dangerous FOR variable. If you attempt to access the variable using %%~ at the end of a line, you can get unpredictable results, and may even crash CMD.EXE! The only reliable way to access it without restrictions is to use %%~~, which of course strips any enclosing quotes.

对于变量来说,~是一个潜在的危险。如果您试图在一行的末尾使用%%~来访问变量,您可能会得到不可预测的结果,甚至可能会崩溃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 safefor /f %%~ in ("A") do echo This works even at end of line: %%~~

The <SUB> (0x1A) character is special because <SUB> literals embedded within batch scripts are read as linefeeds (<LF>). In order to use <SUB> as a FOR variable, the value must be somehow stored within an environment variable, and then %%%VAR% will work for both definition and access.

(0x1A)字符是特殊的,因为在批处理脚本中嵌入的文字被读为linefeed ( )。为了使用 作为变量,值必须以某种方式存储在一个环境变量中,然后%%% %%% %%VAR%将同时用于定义和访问。

As already stated, a single FOR /F can parse and assign a maximum of 31 tokens. For example:

如前所述,一个FOR /F可以解析和分配最多31个令牌。例如:

@echo offsetlocal enableDelayedExpansionset "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 _=%%_

The above yields A=1 _=31 Note - tokens 2-30 work just fine, I just wanted a small example

上面的A=1 =1 _=31,代币2-30就可以了,我只是想举个小例子。

Any attempt to parse and assign more than 31 tokens will silently fail without setting ERRORLEVEL.

任何解析和分配超过31个令牌的尝试都将无声地失败,而不会设置错误级别。

@echo offsetlocal enableDelayedExpansionset "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

You can parse and assign up to 31 tokens and assign the remainder to another token as follows:

您可以解析和分配31个令牌,并将剩下的标记分配给另一个令牌:

@echo offsetlocal enableDelayedExpansionset "str="for /l %%0 in (1 1 35) do set "str=!str! %%n"for /f "tokens=1-31*" %%@ in ("!str!") do echo @=%%A  ^^=%%^^  _=%%_

The above yields @=1 ^=31 _=32 33 34 35

上述收益率@ 31 = 1 ^ = _ = 32 33 34 35

And now for the really bad news. A single FOR /F can never parse more than 31 tokens, as I learned when I looked at Number of tokens limit in a FOR command in a Windows batch script

现在是真正的坏消息。一个FOR /F不能解析超过31个令牌,这是我在Windows批处理脚本中查看FOR命令中的令牌数量限制时学到的

@echo offsetlocal enableDelayedExpansionset "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

The very unfortunate output is A=1 B=31 C=%C

非常不幸的输出是A=1 B=31 C=%C。

#2


4  

My answer is comprised of two parts. The first one is a new answer I posted in help-in-writing-a-batch-script-to-parse-csv-file-and-output-a-text-file question that have not any limit in the number of fields.

我的答案由两部分组成。第一个是我在help-in- write -a-batch-script-to-parse-csv-file- output-a-text-file问题中发布的一个新答案,这个问题在字段的数量上没有任何限制。

The second part is a modification to that answer that allows to select which fields will be extracted from the csv file by additional parameters placed after the file name. The modified code is in UPPERCASE LETTERS.

第二部分是对该答案的修改,允许通过文件名称后面的附加参数从csv文件中提取哪些字段。修改后的代码是大写字母。

@echo offsetlocal EnableDelayedExpansionrem Create heading array:set /P headingRow=< %1set i=0for %%h in (%headingRow%) do (    set /A i+=1    set heading[!i!]=%%~h)REM SAVE FILE NAME AND CREATE TARGET ELEMENTS ARRAY:SET FILENAME=%1IF "%2" == "" (FOR /L %%J IN (1,1,%i%) DO SET TARGET[%%J]=%%J) & GOTO CONTINUESET J=0:NEXTTARGET    SHIFT    IF "%1" == "" GOTO CONTINUE    SET /A J+=1    SET TARGET[%J%]=%1GOTO NEXTTARGET:CONTINUErem Process the file:call :ProcessFile < %FILENAME%exit /B:ProcessFileset /P line=:nextLine    set line=:EOF    set /P line=    if "!line!" == ":EOF" goto :EOF    set i=0    SET J=1    for %%e in (%line%) do (        set /A i+=1        FOR %%J IN (!J!) DO SET TARGET=!TARGET[%%J]!        IF !i! == !TARGET! (            for %%i in (!i!) do echo !heading[%%i]!%%~e            SET /A J+=1        )    )goto nextLineexit /B

For example:

例如:

EXTRACTCSVFIELDS THEFILE.CSV 7 12 15 18

EDIT A simpler method

编辑一个简单的方法

Below is a new version that is both simpler and easier to understand because it use a list of target elements instead of an array:

下面是一个新版本,它既简单又容易理解,因为它使用的是目标元素列表而不是数组:

@echo offsetlocal EnableDelayedExpansionrem Create heading array:set /P headingRow=< %1set i=0for %%h in (%headingRow%) do (    set /A i+=1    set heading[!i!]=%%~h)REM CREATE TARGET ELEMENTS LIST:IF "%2" == "" (    SET TARGETLIST=    FOR /L %%J IN (1,1,%i%) DO SET TARGETLIST=!TARGETLIST! %%J) ELSE (    SET TARGETLIST=%*    SET TARGETLIST=!TARGETLIST:* =!)rem Process the file:call :ProcessFile < %1exit /B:ProcessFileset /P line=:nextLine    set line=:EOF    set /P line=    if "!line!" == ":EOF" goto :EOF    set i=0    for %%e in (%line%) do (        set /A i+=1        for %%i IN (!i!) DO (            IF "!TARGETLIST:%%i=!" NEQ "!TARGETLIST!" (                echo !heading[%%i]!%%~e            )        )    )goto nextLineexit /B

Also, this version does not require the desired fields be given in order.

此外,这个版本不需要按顺序给出所需的字段。

EDIT

编辑

Oops! The for parameters stuff distracted my attention, so I was not aware of your last request:

哦!for参数的事情分散了我的注意力,所以我没有注意到你最后的要求:

"Ultimately I want to make a string which will be something like:field7,field12,field15,field18"

Just modify the last part of the program to do that:

只需修改程序的最后一部分即可:

:ProcessFileset /P line=:nextLine    set line=:EOF    set /P line=    if "!line!" == ":EOF" goto :EOF    set i=0    set resultString=    for %%e in (%line%) do (        set /A i+=1        for %%i IN (!i!) DO (            IF "!TARGETLIST:%%i=!" NEQ "!TARGETLIST!" (                set resultString=!resultString!%%~e,            )        )    )    set resultString=%resultString:~0,-1%    echo Process here the "%resultString%"goto nextLineexit /B

You may also remove the creation of the heading array, because you want NOT the headings! ;)

您也可以删除标题数组的创建,因为您不想要标题!,)

#3


1  

Using %%@ and %%` (not documented here) as start variables the max you can get is 71:

使用%@和% '(这里没有记录)作为起始变量,最多可以得到71:

@echo offfor /f "tokens=1-31* delims=," %%@ in ("%filename%") do (    echo:    echo  1=%%@    echo  2=%%A    echo  3=%%B    echo  4=%%C    echo  5=%%D    echo  6=%%E    echo  7=%%F    echo  8=%%G    echo  9=%%H    echo 10=%%I    echo 11=%%J    echo 12=%%K    echo 13=%%L    echo 14=%%M    echo 15=%%N    echo 16=%%O    echo 17=%%P    echo 18=%%Q    echo 19=%%R    echo 20=%%S    echo 21=%%T    echo 22=%%U    echo 23=%%V    echo 24=%%W    echo 25=%%X    echo 26=%%Y    echo 27=%%Z    echo 28=%%[    echo 29=%%\    echo 30=%%]    echo 31=%%^^    for /F "tokens=1-30* delims=," %%` in ("%%_") do (        echo 32=%%`        echo 33=%%a        echo 34=%%b        echo 35=%%c        echo 36=%%d        echo 37=%%e        echo 38=%%f        echo 39=%%g        echo 40=%%h        echo 41=%%i        echo 42=%%j        echo 43=%%k        echo 44=%%l        echo 45=%%m        echo 46=%%n        echo 47=%%o        echo 48=%%p        echo 49=%%q        echo 50=%%r        echo 51=%%s        echo 52=%%t        echo 53=%%u        echo 54=%%v        echo 55=%%w        echo 56=%%x        echo 57=%%y        echo 58=%%z        echo 59=%%{        echo 60=%%^|        echo 61=%%}        for /F "tokens=1-9* delims=," %%0 in ("%%~") do (            echo 62=%%0            echo 63=%%1            echo 64=%%2            echo 65=%%3            echo 66=%%4            echo 67=%%5            echo 68=%%6            echo 69=%%7            echo 70=%%8            echo 71=%%9        )    ))

#4


0  

When I read this problem again and the solution proposed in the most-voted answer, I thought that a much simpler way to make good use of a series of nested FOR /F commands could be developed. I started to write such a method, that would allowed to use 127 additional tokens placing they in the ASCII 128-254 characters range. However, when my program was completed I discovered that the ASCII characters in the "natural" 128..254 order could not be used for this purpose...

当我再次阅读这个问题并在投票次数最多的答案中提出解决方案时,我认为可以开发一种更简单的方法来充分利用一系列嵌套的FOR /F命令。我开始编写这样一个方法,它允许使用127个附加令牌将它们放在ASCII 128-254字符范围内。然而,当我的程序完成时,我发现ASCII字符在“自然”128中。订单不能用于此目的……

Then, a group of people were interested in this problem and they made a series of discoveries and developments that culminated in a method that allows to use many tokens (more than 43,000!) in a series of nested FOR /F commands. You may read a detailed description of the research and development involved in this discovery at this DosTips topic.

然后,一组人对这个问题感兴趣,他们进行了一系列的发现和开发,最终得到了一个方法,该方法允许在一系列嵌套FOR /F命令中使用许多令牌(超过43,000!)在这个DosTips主题中,您可以阅读关于这个发现所涉及的研究和开发的详细描述。

Finally, I used the new method to modify my program, so it now allows the processing of up to 4094 simultaneous tokens (from a text file with long lines), but in a simple way. My application consists in a Batch file, called MakeForTokens.bat, that you may run with the number of desired tokens in the parameter. For example:

最后,我使用了新的方法来修改我的程序,所以现在它允许处理最多4094个同时发生的令牌(来自一个长行的文本文件),但是是以一种简单的方式。我的应用程序包含一个名为makefortoken的批处理文件。bat,您可以在参数中使用所需的令牌数量。例如:

MakeForTokens.bat 64

The program generates a Batch file, called ForTokens.bat, that contain all the code necessary to manage such an amount of simultaneous tokens, including examples of how to process a file. In this way, the users just needs to insert their own file names and desired tokens in order to get a working program.

程序生成一个批处理文件,称为fortoken。bat,包含管理这么多同时发生的令牌所需的所有代码,包括如何处理文件的示例。通过这种方式,用户只需插入自己的文件名和所需的令牌,就可以获得一个有效的程序。

In this particular case, this would be the final ForTokens.bat file that solve the problem as stated in this question, after most descriptive comments were deleted:

在这种特殊情况下,这将是令牌的最终用途。解决问题的bat文件,在删除了大部分描述性注释后:

@echo off & setlocal EnableDelayedExpansion & set "$numTokens=65"Rem/For  Step 1: Define the series of auxiliary variables that will be used as FOR tokens.call :DefineForTokensRem/For  Step 2:  Define an auxiliary variable that will contain the desired tokens when it is %expanded%.call :ExpandTokensString "tokens=7,12,15,18"Rem/For  Step 3:  Define the variable with the "delims" value that will be used in the nested FOR's.set "delims=delims=,"Rem/For  Step 4:  Create the macro that contain the nested FOR's.call :CreateNestedForsRem/For  Step 5:  This is the main FOR /F command that process the file.for /F "usebackq tokens=1-31* %delims%" %%%$1% in ("filename.txt") do %NestedFors% (   Rem/For  Step 6: Process the tokens.   Rem/For  To just show they, use the "tokens" variable defined above:   echo %tokens%   Rem/For  You may also process individual tokens via another FOR /F command:   for /F "tokens=1-%tokens.len%" %%a in ("%tokens%") do (      echo Field  #7: %%a      echo Field #12: %%b      echo Field #15: %%c      echo Field #18: %%d   ))goto :EOFSupport subroutines. You must not modify any code below this line.:DefineForTokensfor /F "tokens=2 delims=:." %%p in ('chcp') do set /A "_cp=%%p, _pages=($numTokens/256+1)*2"set "_hex= 0 1 2 3 4 5 6 7 8 9 A B C D E F"call set "_pages=%%_hex:~0,%_pages%%%"if %$numTokens% gtr 2048 echo Creating FOR tokens variables, please wait . . .(   echo FF FE   for %%P in (%_pages%) do for %%A in (%_hex%) do for %%B in (%_hex%) do echo %%A%%B 3%%P 0D 00 0A 00) > "%temp%\forTokens.hex.txt"certutil.exe -decodehex -f "%temp%\forTokens.hex.txt" "%temp%\forTokens.utf-16le.bom.txt" >NULchcp 65001 >NULtype "%temp%\forTokens.utf-16le.bom.txt" > "%temp%\forTokens.utf8.txt"(for /L %%N in (0,1,%$numTokens%) do set /P "$%%N=")  < "%temp%\forTokens.utf8.txt" chcp %_cp% >NULdel "%temp%\forTokens.*.txt"for %%v in (_cp _hex _pages) do set "%%v="exit /B:CreateNestedForssetlocal EnableDelayedExpansionset /A "numTokens=$numTokens-1, mod=numTokens%%31, i=numTokens/31, lim=31"if %mod% equ 0 set "mod=31"set "NestedFors="for /L %%i in (32,31,%numTokens%) do (   if !i! equ 1 set "lim=!mod!"   set "NestedFors=!NestedFors! for /F "tokens=1-!lim!* %delims%" %%!$%%i! in ("%%!$%%i!") do"   set /A "i-=1")for /F "delims=" %%a in ("!NestedFors!") do endlocal & set "NestedFors=%%a"exit /B:ExpandTokensString variable=tokens definitions ...setlocal EnableDelayedExpansionset "var=" & set "tokens=" & set "len=0"if "%~2" equ "" (set "params=%~1") else set "params=%*"for %%a in (!params!) do (   if not defined var (      set "var=%%a"   ) else for /F "tokens=1-3 delims=-+" %%i in ("%%a") do (      if "%%j" equ "" (         if %%i lss %$numTokens% set "tokens=!tokens! %%!$%%i!" & set /A len+=1      ) else (         if "%%k" equ "" (set "k=1") else set "k=%%k"         if %%i leq %%j (            for /L %%n in (%%i,!k!,%%j) do if %%n lss %$numTokens% set "tokens=!tokens! %%!$%%n!" & set /A len+=1         ) else (            for /L %%n in (%%i,-!k!,%%j) do if %%n lss %$numTokens% set "tokens=!tokens! %%!$%%n!" & set /A len+=1         )      )   ))endlocal & set "%var%=%tokens%" & set "%var%.len=%len%"exit /B

You may download the MakeForTokens.bat application from this site.

您可以下载makefortoken。bat应用程序从这个站点。

#1


15  

Important update - I don't think Windows batch is a good option for your needs because a single FOR /F cannot parse more than 31 tokens. See the bottom of the Addendum below for an explanation.

重要的更新——我不认为Windows批处理对您的需求是一个好的选择,因为单个for /F不能解析31个令牌。有关解释,请参阅下面附录的底部。

However, it is possible to do what you want with batch. This ugly code will give you access to all 64 tokens.

但是,可以使用批处理来完成您想要的操作。这个难看的代码将使您能够访问所有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    )  ))

The addendum provides important info on how the above works.

附录提供了关于上述工作原理的重要信息。

If you only need a few of the tokens spread out amongst the 64 on the line, then the solution is marginally easier in that you might be able to avoid using crazy characters as FOR variables. But there is still careful bookkeeping to be done.

如果您只需要在队列中的64个标记中展开一些标记,那么解决方案就稍微容易一些,因为您可能可以避免使用疯狂字符作为变量。但仍有一些谨慎的簿记工作要做。

For example, the following will give you access to tokens 5, 27, 46 and 64

例如,下面将提供对令牌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    )  ))

April 2016 Update - Based on investigative work by DosTips users Aacini, penpen, and aGerman, I have developed a relatively easy method to simultaneously access thousands of tokens using FOR /F. The work is part of this DosTips thread. The actual code can be found in these 3 posts:

2016年4月更新——基于DosTips用户Aacini、penpen和aGerman的调查工作,我开发了一种相对简单的方法,可以同时使用FOR /F访问数千个令牌。这项工作是这个DosTips线程的一部分。实际代码可以在这3篇文章中找到:

Original AnswerFOR variables are limited to a single character, so your %%BL strategy can't work. The variables are case sensitive. According to Microsoft you are limited to capturing 26 tokens within one FOR statement, but it is possible to get more if you use more than just alpha. Its a pain because you need an ASCII table to figure out which characters go where. FOR does not allow just any character however, and the maximum number of tokens that a single FOR /F can assign is 31 +1. Any attempt to parse and assign more than 31 will quietly fail, as you have discovered.

变量的原始答案仅限于单个字符,因此您的%BL策略不能工作。变量是区分大小写的。根据微软的规定,你只能在一条语句中捕获26个令牌,但如果你使用的不仅仅是alpha,你可能会得到更多。这很麻烦,因为您需要一个ASCII表来确定哪些字符可以移动到哪里。然而,FOR不允许只允许任何字符,而且单FOR /F可以分配的令牌的最大数量是31 +1。任何解析和分配超过31个的尝试都会悄无声息地失败,正如您所发现的。

Thankfully, I don't think you need that many tokens. You simply specify which tokens you want with the TOKENS option.

谢天谢地,我想你不需要那么多代币。您只需使用令牌选项指定需要的令牌。

for /f "usebackq tokens=7,12,15,18 delims=," %%A in ("%filename%") do echo %%A,%%B,%%C,%%D

will give you your 7th, 12th, 15th and 18th tokens.

会给你第7、12、15和18个代币。

Addendum

齿顶高

April 2016 Update A couple weeks ago I learned that the following rules (written 6 years ago) are code page dependent. The data below has been verified for code pages 437 and 850. More importantly, the FOR variable sequence of extended ASCII characters 128-254 does not match the byte code value, and varies tremendously by code page. It turns out the FOR /F variable mapping is based on the underlying UTF-(16?) code point. So the extended ASCII characters are of limited use when used with FOR /F. See the thread at http://www.dostips.com/forum/viewtopic.php?f=3&t=7703 for more information.

2016年4月更新几周前,我了解到以下规则(6年前编写)是依赖于代码页的。下面的数据已经验证了代码页437和850。更重要的是,对于扩展ASCII字符128-254的变量序列与字节码值不匹配,且代码页差异很大。结果证明FOR /F变量映射基于底层的UTF-(16?)代码点。因此扩展的ASCII字符在与FOR /F使用时是有限的。请参阅http://www.doets com/forum/viewtopic.php?f = 3科技= 7703的更多信息。

I performed some tests, and can report the following (updated in response to jeb's comment):

我做了一些测试,可以报告如下(针对jeb的评论更新):

Most characters can be used as a FOR variable, including extended ASCII 128-254. But some characters cannot be used to define a variable in the first part of a FOR statement, but can be used in the DO clause. A few can't be used for either. Some have no restrictions, but require special syntax.

大多数字符都可以用作变量,包括扩展的ASCII 128-254。但是有些字符不能用于在FOR语句的第一部分中定义变量,但是可以在DO子句中使用。有几个都不能用。有些没有限制,但需要特殊的语法。

The following is a summary of characters that have restrictions or require special syntax. Note that text within angle brackets like <space> represents a single character.

下面是具有限制或需要特殊语法的字符的摘要。注意,像 这样的尖括号内的文本表示一个字符。

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

Special characters like ^ < > | & must be either escaped or quoted. For example, the following works:

等特殊字符^ < > | &必须逃跑或引用。例如,以下作品:

for /f %%^< in ("OK") do echo "%%<" %%^<

Some characters cannot be used to define a FOR variable. For example, the following gives a syntax error:

有些字符不能用于定义变量a。例如,下面给出一个语法错误:

for /f %%^= in ("No can do") do echo anything

But %%= can be implicitly defined by using the TOKENS option, and the value accessed in the DO clause like so:

但是%%=可以通过使用令牌选项隐式定义,并且DO子句中访问的值如下所示:

for /f "tokens=1-3" %%^< in ("A B C") do echo %%^< %%^= %%^>

The % is odd - You can define a FOR variable using %%%%. But The value cannot be accessed unless you use the ~ modifier. This means enclosing quotes cannot be preserved.

%是奇数-可以使用%%%% %为变量定义a。但是,除非使用~修饰符,否则无法访问该值。这意味着引号不能被保留。

for /f "usebackq tokens=1,2" %%%% in ('"A"') do echo %%%% %%~%%

The above yields %% A

上述收益率为% A

The ~ is a potentially dangerous FOR variable. If you attempt to access the variable using %%~ at the end of a line, you can get unpredictable results, and may even crash CMD.EXE! The only reliable way to access it without restrictions is to use %%~~, which of course strips any enclosing quotes.

对于变量来说,~是一个潜在的危险。如果您试图在一行的末尾使用%%~来访问变量,您可能会得到不可预测的结果,甚至可能会崩溃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 safefor /f %%~ in ("A") do echo This works even at end of line: %%~~

The <SUB> (0x1A) character is special because <SUB> literals embedded within batch scripts are read as linefeeds (<LF>). In order to use <SUB> as a FOR variable, the value must be somehow stored within an environment variable, and then %%%VAR% will work for both definition and access.

(0x1A)字符是特殊的,因为在批处理脚本中嵌入的文字被读为linefeed ( )。为了使用 作为变量,值必须以某种方式存储在一个环境变量中,然后%%% %%% %%VAR%将同时用于定义和访问。

As already stated, a single FOR /F can parse and assign a maximum of 31 tokens. For example:

如前所述,一个FOR /F可以解析和分配最多31个令牌。例如:

@echo offsetlocal enableDelayedExpansionset "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 _=%%_

The above yields A=1 _=31 Note - tokens 2-30 work just fine, I just wanted a small example

上面的A=1 =1 _=31,代币2-30就可以了,我只是想举个小例子。

Any attempt to parse and assign more than 31 tokens will silently fail without setting ERRORLEVEL.

任何解析和分配超过31个令牌的尝试都将无声地失败,而不会设置错误级别。

@echo offsetlocal enableDelayedExpansionset "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

You can parse and assign up to 31 tokens and assign the remainder to another token as follows:

您可以解析和分配31个令牌,并将剩下的标记分配给另一个令牌:

@echo offsetlocal enableDelayedExpansionset "str="for /l %%0 in (1 1 35) do set "str=!str! %%n"for /f "tokens=1-31*" %%@ in ("!str!") do echo @=%%A  ^^=%%^^  _=%%_

The above yields @=1 ^=31 _=32 33 34 35

上述收益率@ 31 = 1 ^ = _ = 32 33 34 35

And now for the really bad news. A single FOR /F can never parse more than 31 tokens, as I learned when I looked at Number of tokens limit in a FOR command in a Windows batch script

现在是真正的坏消息。一个FOR /F不能解析超过31个令牌,这是我在Windows批处理脚本中查看FOR命令中的令牌数量限制时学到的

@echo offsetlocal enableDelayedExpansionset "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

The very unfortunate output is A=1 B=31 C=%C

非常不幸的输出是A=1 B=31 C=%C。

#2


4  

My answer is comprised of two parts. The first one is a new answer I posted in help-in-writing-a-batch-script-to-parse-csv-file-and-output-a-text-file question that have not any limit in the number of fields.

我的答案由两部分组成。第一个是我在help-in- write -a-batch-script-to-parse-csv-file- output-a-text-file问题中发布的一个新答案,这个问题在字段的数量上没有任何限制。

The second part is a modification to that answer that allows to select which fields will be extracted from the csv file by additional parameters placed after the file name. The modified code is in UPPERCASE LETTERS.

第二部分是对该答案的修改,允许通过文件名称后面的附加参数从csv文件中提取哪些字段。修改后的代码是大写字母。

@echo offsetlocal EnableDelayedExpansionrem Create heading array:set /P headingRow=< %1set i=0for %%h in (%headingRow%) do (    set /A i+=1    set heading[!i!]=%%~h)REM SAVE FILE NAME AND CREATE TARGET ELEMENTS ARRAY:SET FILENAME=%1IF "%2" == "" (FOR /L %%J IN (1,1,%i%) DO SET TARGET[%%J]=%%J) & GOTO CONTINUESET J=0:NEXTTARGET    SHIFT    IF "%1" == "" GOTO CONTINUE    SET /A J+=1    SET TARGET[%J%]=%1GOTO NEXTTARGET:CONTINUErem Process the file:call :ProcessFile < %FILENAME%exit /B:ProcessFileset /P line=:nextLine    set line=:EOF    set /P line=    if "!line!" == ":EOF" goto :EOF    set i=0    SET J=1    for %%e in (%line%) do (        set /A i+=1        FOR %%J IN (!J!) DO SET TARGET=!TARGET[%%J]!        IF !i! == !TARGET! (            for %%i in (!i!) do echo !heading[%%i]!%%~e            SET /A J+=1        )    )goto nextLineexit /B

For example:

例如:

EXTRACTCSVFIELDS THEFILE.CSV 7 12 15 18

EDIT A simpler method

编辑一个简单的方法

Below is a new version that is both simpler and easier to understand because it use a list of target elements instead of an array:

下面是一个新版本,它既简单又容易理解,因为它使用的是目标元素列表而不是数组:

@echo offsetlocal EnableDelayedExpansionrem Create heading array:set /P headingRow=< %1set i=0for %%h in (%headingRow%) do (    set /A i+=1    set heading[!i!]=%%~h)REM CREATE TARGET ELEMENTS LIST:IF "%2" == "" (    SET TARGETLIST=    FOR /L %%J IN (1,1,%i%) DO SET TARGETLIST=!TARGETLIST! %%J) ELSE (    SET TARGETLIST=%*    SET TARGETLIST=!TARGETLIST:* =!)rem Process the file:call :ProcessFile < %1exit /B:ProcessFileset /P line=:nextLine    set line=:EOF    set /P line=    if "!line!" == ":EOF" goto :EOF    set i=0    for %%e in (%line%) do (        set /A i+=1        for %%i IN (!i!) DO (            IF "!TARGETLIST:%%i=!" NEQ "!TARGETLIST!" (                echo !heading[%%i]!%%~e            )        )    )goto nextLineexit /B

Also, this version does not require the desired fields be given in order.

此外,这个版本不需要按顺序给出所需的字段。

EDIT

编辑

Oops! The for parameters stuff distracted my attention, so I was not aware of your last request:

哦!for参数的事情分散了我的注意力,所以我没有注意到你最后的要求:

"Ultimately I want to make a string which will be something like:field7,field12,field15,field18"

Just modify the last part of the program to do that:

只需修改程序的最后一部分即可:

:ProcessFileset /P line=:nextLine    set line=:EOF    set /P line=    if "!line!" == ":EOF" goto :EOF    set i=0    set resultString=    for %%e in (%line%) do (        set /A i+=1        for %%i IN (!i!) DO (            IF "!TARGETLIST:%%i=!" NEQ "!TARGETLIST!" (                set resultString=!resultString!%%~e,            )        )    )    set resultString=%resultString:~0,-1%    echo Process here the "%resultString%"goto nextLineexit /B

You may also remove the creation of the heading array, because you want NOT the headings! ;)

您也可以删除标题数组的创建,因为您不想要标题!,)

#3


1  

Using %%@ and %%` (not documented here) as start variables the max you can get is 71:

使用%@和% '(这里没有记录)作为起始变量,最多可以得到71:

@echo offfor /f "tokens=1-31* delims=," %%@ in ("%filename%") do (    echo:    echo  1=%%@    echo  2=%%A    echo  3=%%B    echo  4=%%C    echo  5=%%D    echo  6=%%E    echo  7=%%F    echo  8=%%G    echo  9=%%H    echo 10=%%I    echo 11=%%J    echo 12=%%K    echo 13=%%L    echo 14=%%M    echo 15=%%N    echo 16=%%O    echo 17=%%P    echo 18=%%Q    echo 19=%%R    echo 20=%%S    echo 21=%%T    echo 22=%%U    echo 23=%%V    echo 24=%%W    echo 25=%%X    echo 26=%%Y    echo 27=%%Z    echo 28=%%[    echo 29=%%\    echo 30=%%]    echo 31=%%^^    for /F "tokens=1-30* delims=," %%` in ("%%_") do (        echo 32=%%`        echo 33=%%a        echo 34=%%b        echo 35=%%c        echo 36=%%d        echo 37=%%e        echo 38=%%f        echo 39=%%g        echo 40=%%h        echo 41=%%i        echo 42=%%j        echo 43=%%k        echo 44=%%l        echo 45=%%m        echo 46=%%n        echo 47=%%o        echo 48=%%p        echo 49=%%q        echo 50=%%r        echo 51=%%s        echo 52=%%t        echo 53=%%u        echo 54=%%v        echo 55=%%w        echo 56=%%x        echo 57=%%y        echo 58=%%z        echo 59=%%{        echo 60=%%^|        echo 61=%%}        for /F "tokens=1-9* delims=," %%0 in ("%%~") do (            echo 62=%%0            echo 63=%%1            echo 64=%%2            echo 65=%%3            echo 66=%%4            echo 67=%%5            echo 68=%%6            echo 69=%%7            echo 70=%%8            echo 71=%%9        )    ))

#4


0  

When I read this problem again and the solution proposed in the most-voted answer, I thought that a much simpler way to make good use of a series of nested FOR /F commands could be developed. I started to write such a method, that would allowed to use 127 additional tokens placing they in the ASCII 128-254 characters range. However, when my program was completed I discovered that the ASCII characters in the "natural" 128..254 order could not be used for this purpose...

当我再次阅读这个问题并在投票次数最多的答案中提出解决方案时,我认为可以开发一种更简单的方法来充分利用一系列嵌套的FOR /F命令。我开始编写这样一个方法,它允许使用127个附加令牌将它们放在ASCII 128-254字符范围内。然而,当我的程序完成时,我发现ASCII字符在“自然”128中。订单不能用于此目的……

Then, a group of people were interested in this problem and they made a series of discoveries and developments that culminated in a method that allows to use many tokens (more than 43,000!) in a series of nested FOR /F commands. You may read a detailed description of the research and development involved in this discovery at this DosTips topic.

然后,一组人对这个问题感兴趣,他们进行了一系列的发现和开发,最终得到了一个方法,该方法允许在一系列嵌套FOR /F命令中使用许多令牌(超过43,000!)在这个DosTips主题中,您可以阅读关于这个发现所涉及的研究和开发的详细描述。

Finally, I used the new method to modify my program, so it now allows the processing of up to 4094 simultaneous tokens (from a text file with long lines), but in a simple way. My application consists in a Batch file, called MakeForTokens.bat, that you may run with the number of desired tokens in the parameter. For example:

最后,我使用了新的方法来修改我的程序,所以现在它允许处理最多4094个同时发生的令牌(来自一个长行的文本文件),但是是以一种简单的方式。我的应用程序包含一个名为makefortoken的批处理文件。bat,您可以在参数中使用所需的令牌数量。例如:

MakeForTokens.bat 64

The program generates a Batch file, called ForTokens.bat, that contain all the code necessary to manage such an amount of simultaneous tokens, including examples of how to process a file. In this way, the users just needs to insert their own file names and desired tokens in order to get a working program.

程序生成一个批处理文件,称为fortoken。bat,包含管理这么多同时发生的令牌所需的所有代码,包括如何处理文件的示例。通过这种方式,用户只需插入自己的文件名和所需的令牌,就可以获得一个有效的程序。

In this particular case, this would be the final ForTokens.bat file that solve the problem as stated in this question, after most descriptive comments were deleted:

在这种特殊情况下,这将是令牌的最终用途。解决问题的bat文件,在删除了大部分描述性注释后:

@echo off & setlocal EnableDelayedExpansion & set "$numTokens=65"Rem/For  Step 1: Define the series of auxiliary variables that will be used as FOR tokens.call :DefineForTokensRem/For  Step 2:  Define an auxiliary variable that will contain the desired tokens when it is %expanded%.call :ExpandTokensString "tokens=7,12,15,18"Rem/For  Step 3:  Define the variable with the "delims" value that will be used in the nested FOR's.set "delims=delims=,"Rem/For  Step 4:  Create the macro that contain the nested FOR's.call :CreateNestedForsRem/For  Step 5:  This is the main FOR /F command that process the file.for /F "usebackq tokens=1-31* %delims%" %%%$1% in ("filename.txt") do %NestedFors% (   Rem/For  Step 6: Process the tokens.   Rem/For  To just show they, use the "tokens" variable defined above:   echo %tokens%   Rem/For  You may also process individual tokens via another FOR /F command:   for /F "tokens=1-%tokens.len%" %%a in ("%tokens%") do (      echo Field  #7: %%a      echo Field #12: %%b      echo Field #15: %%c      echo Field #18: %%d   ))goto :EOFSupport subroutines. You must not modify any code below this line.:DefineForTokensfor /F "tokens=2 delims=:." %%p in ('chcp') do set /A "_cp=%%p, _pages=($numTokens/256+1)*2"set "_hex= 0 1 2 3 4 5 6 7 8 9 A B C D E F"call set "_pages=%%_hex:~0,%_pages%%%"if %$numTokens% gtr 2048 echo Creating FOR tokens variables, please wait . . .(   echo FF FE   for %%P in (%_pages%) do for %%A in (%_hex%) do for %%B in (%_hex%) do echo %%A%%B 3%%P 0D 00 0A 00) > "%temp%\forTokens.hex.txt"certutil.exe -decodehex -f "%temp%\forTokens.hex.txt" "%temp%\forTokens.utf-16le.bom.txt" >NULchcp 65001 >NULtype "%temp%\forTokens.utf-16le.bom.txt" > "%temp%\forTokens.utf8.txt"(for /L %%N in (0,1,%$numTokens%) do set /P "$%%N=")  < "%temp%\forTokens.utf8.txt" chcp %_cp% >NULdel "%temp%\forTokens.*.txt"for %%v in (_cp _hex _pages) do set "%%v="exit /B:CreateNestedForssetlocal EnableDelayedExpansionset /A "numTokens=$numTokens-1, mod=numTokens%%31, i=numTokens/31, lim=31"if %mod% equ 0 set "mod=31"set "NestedFors="for /L %%i in (32,31,%numTokens%) do (   if !i! equ 1 set "lim=!mod!"   set "NestedFors=!NestedFors! for /F "tokens=1-!lim!* %delims%" %%!$%%i! in ("%%!$%%i!") do"   set /A "i-=1")for /F "delims=" %%a in ("!NestedFors!") do endlocal & set "NestedFors=%%a"exit /B:ExpandTokensString variable=tokens definitions ...setlocal EnableDelayedExpansionset "var=" & set "tokens=" & set "len=0"if "%~2" equ "" (set "params=%~1") else set "params=%*"for %%a in (!params!) do (   if not defined var (      set "var=%%a"   ) else for /F "tokens=1-3 delims=-+" %%i in ("%%a") do (      if "%%j" equ "" (         if %%i lss %$numTokens% set "tokens=!tokens! %%!$%%i!" & set /A len+=1      ) else (         if "%%k" equ "" (set "k=1") else set "k=%%k"         if %%i leq %%j (            for /L %%n in (%%i,!k!,%%j) do if %%n lss %$numTokens% set "tokens=!tokens! %%!$%%n!" & set /A len+=1         ) else (            for /L %%n in (%%i,-!k!,%%j) do if %%n lss %$numTokens% set "tokens=!tokens! %%!$%%n!" & set /A len+=1         )      )   ))endlocal & set "%var%=%tokens%" & set "%var%.len=%len%"exit /B

You may download the MakeForTokens.bat application from this site.

您可以下载makefortoken。bat应用程序从这个站点。