Jef*_*ebb 6 windows csv cmd batch-file
我在另一个页面上看到了一个响应(帮助编写一个批处理脚本来解析CSV文件并输出一个文本文件) - 精彩的代码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
Run Code Online (Sandbox Code Playgroud)
它非常出色地用于我以下格式制作的示例csv文件:
Header,Name,Place
one,two,three
four,five,six
Run Code Online (Sandbox Code Playgroud)
但是,我想要更改的实际文件包含64个字段 - 因此我更改了tokens=1-10
to tokens=1-64
并将%%a
等增加到最多64个变量(%%BL
例如,最后一个被调用).但是,现在,当我在我的'大'csv文件(带有64个令牌)上运行批处理时,没有任何反应.没有错误(好)但没有输出!(坏).如果有人可以提供帮助,那就太棒了......如果我可以指出这最后一点,那就太接近整个应用了!或者,如果有人有一些示例代码将对无限数量的令牌执行类似的操作...最终我想创建一个类似于以下内容的字符串:
field7,field12,field15,field18
Run Code Online (Sandbox Code Playgroud)
dbe*_*ham 16
重要更新 - 我不认为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
)
)
)
Run Code Online (Sandbox Code Playgroud)
该附录提供了有关上述工作原理的重要信息.
如果您只需要在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
)
)
)
Run Code Online (Sandbox Code Playgroud)
2016年4月更新 - 基于DosTips用户Aacini,penpen和aGerman的调查工作,我开发了一种相对简单的方法,可以使用FOR/F同时访问数千个令牌.这项工作是这个DosTips线程的一部分.实际代码可以在这3个帖子中找到:
原始答案 FOR变量仅限于单个字符,因此您的%% BL策略无法正常工作.变量区分大小写.根据微软的说法,你只能在一个FOR语句中捕获26个令牌,但如果你使用的不仅仅是alpha,那么它可能会获得更多.这很痛苦,因为你需要一个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
Run Code Online (Sandbox Code Playgroud)
会给你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
Run Code Online (Sandbox Code Playgroud)
特殊字符^
<
>
|
&
必须是转义或引用.例如,以下工作:
for /f %%^< in ("OK") do echo "%%<" %%^<
Run Code Online (Sandbox Code Playgroud)
某些字符不能用于定义FOR变量.例如,以下内容给出了语法错误:
for /f %%^= in ("No can do") do echo anything
Run Code Online (Sandbox Code Playgroud)
但是%%=
可以通过使用TOKENS选项隐式定义,并且在DO子句中访问的值如下:
for /f "tokens=1-3" %%^< in ("A B C") do echo %%^< %%^= %%^>
Run Code Online (Sandbox Code Playgroud)
该%
是奇数-您可以定义一个FOR变量使用%%%%
.但除非使用~
修饰符,否则无法访问该值.这意味着无法保留封闭引号.
for /f "usebackq tokens=1,2" %%%% in ('"A"') do echo %%%% %%~%%
Run Code Online (Sandbox Code Playgroud)
以上收益率 %% 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: %%~~
Run Code Online (Sandbox Code Playgroud)
在<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 _=%%_
Run Code Online (Sandbox Code Playgroud)
以上产量A=1 _=31
注意 - 令牌2-30工作得很好,我只想要一个小例子
如果不设置ERRORLEVEL,任何解析和分配超过31个令牌的尝试都将无声地失败.
@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
Run Code Online (Sandbox Code Playgroud)
您可以解析并分配最多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 ^^=%%^^ _=%%_
Run Code Online (Sandbox Code Playgroud)
以上收益率 @=1 ^=31 _=32 33 34 35
现在是真正的坏消息.单个FOR/F永远不会解析超过31个令牌,正如我在Windows批处理脚本中查看FOR命令中的令牌数量限制时所学到的
@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
Run Code Online (Sandbox Code Playgroud)
非常不幸的输出是 A=1 B=31 C=%C