我在另一页(Help in writing a batch script to parse CSV file and output a text file)上看到了响应-出色的代码BTW:
@ECHO OFF
IF "%~1"=="" GOTO :EOF
SET "filename=%~1"
SET fcount=0
SET linenum=0
FOR /F "usebackq tokens=1-10 delims=," %%a IN ("%filename%") DO ^
CALL :process "%%a" "%%b" "%%c" "%%d" "%%e" "%%f" "%%g" "%%h" "%%i" "%%j"
GOTO :EOF
:trim
SET "tmp=%~1"
:trimlead
IF NOT "%tmp:~0,1%"==" " GOTO :EOF
SET "tmp=%tmp:~1%"
GOTO trimlead
:process
SET /A linenum+=1
IF "%linenum%"=="1" GOTO picknames
SET ind=0
:display
IF "%fcount%"=="%ind%" (ECHO.&GOTO :EOF)
SET /A ind+=1
CALL :trim %1
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO !f%ind%!!tmp!
ENDLOCAL
SHIFT
GOTO display
:picknames
IF %1=="" GOTO :EOF
CALL :trim %1
SET /a fcount+=1
SET "f%fcount%=%tmp%"
SHIFT
GOTO picknames
它对于以下格式的示例csv文件非常有用:
Header,Name,Place
one,two,three
four,five,six
但是,我要更改的实际文件包含64个字段-因此我将
tokens=1-10
更改为tokens=1-64
,并增加了%%a
等,最多可包含64个变量(例如,最后一个称为%%BL
)。但是,现在,当我在“大” csv文件(带有64个 token )上运行批处理时,什么也没发生。没有错误(良好),但没有输出! (坏的)。如果有人可以帮忙,那真是太棒了……如果我能确定这最后一点,我将使整个应用程序正常工作!或者,如果有人有一些示例代码将对无限数量的标记执行类似的操作……最终,我想制作一个类似于以下内容的字符串:field7,field12,field15,field18
最佳答案
重要更新-我认为Windows批处理不是满足您需求的好选择,因为单个FOR/F不能解析超过31个 token 。有关说明,请参见下面的附录底部。
但是,可以批量处理所需的操作。这个丑陋的代码将使您能够访问所有64个 token 。
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个 token 中散布一些 token ,那么该解决方案将稍微容易一些,因为您可以避免使用疯狂的字符作为FOR变量。但是,仍然需要仔细进行簿记。
例如,以下内容将使您可以访问 token 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同时访问数千个 token 。该作品是this DosTips thread的一部分。实际的代码可以在以下3个帖子中找到:
原始答案
FOR变量限制为单个字符,因此您的%% BL策略无法正常工作。变量区分大小写。根据Microsoft的说法,您只能在一个FOR语句中捕获26个 token ,但是如果您使用的不只是alpha,则有可能获得更多。这很麻烦,因为您需要一个ASCII表来确定哪些字符在哪里。但是,FOR不允许仅使用任何字符,并且单个FOR/F可以分配的最大 token 数为31 +1。正如您所发现的那样,任何尝试分析和分配31个以上的尝试都将悄然失败。
值得庆幸的是,我认为您不需要那么多 token 。您只需使用“ token ”选项指定所需的 token 。
for /f "usebackq tokens=7,12,15,18 delims=," %%A in ("%filename%") do echo %%A,%%B,%%C,%%D
将为您提供第7、12、15和18个 token 。
附录
,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个 token 。例如:
@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
注意- token 2-30正常工作,我只想举一个小例子如果不设置ERRORLEVEL,则任何试图解析和分配31个以上 token 的尝试都将无提示地失败。
@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个 token ,然后将其余 token 分配给另一个 token ,如下所示:
@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
现在是真正的坏消息。 正如我在查看Number of tokens limit in a FOR command in a Windows batch script时所了解的那样,单个FOR/F永远不能解析超过31个 token
@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
关于windows - Windows批处理脚本以解析CSV文件并输出文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8520313/