这是另一个问题(Loop through CSV file with batch - Space issue)
的扩展我有像这样的csv文件内容
name,sex,age,description,date
venu,m,16,test mesg,2012-05-01
test,f,22,"He is good guy
and
brilliant",2012-05-01
我正在使用此命令循环此文件。
For /F "usebackq tokens=1-3 delims=" %%x in (test.csv) Do (
但是由于第二行有换行符,即使文件中有两条记录,我也会得到3条记录。
如何解决这个问题?提前谢谢。
答案 0 :(得分:2)
主要问题似乎是计算一行中的引号 如果引号计数是奇数,那么您需要附加下一行并再次计算引号。
如果你不想遍历所有的字符串,字符串中字符的计数有点棘手。
我在这里使用延迟减少技术,每个引用将被+1
有效替换,并删除所有其他字符。
要以正确的方式开始和终止该行,开头总会有一个额外的+1
,这将由前面的-1
进行补偿。
主要技巧是将每个引号替换为+1
,将一个引号中的完整文本替换为下一个!!#:#=
的完整文本。
由于变量!#:#=...<some text>...!
的内容为+1
,因此#
将始终扩展为+1
,因此搜索模式#
不能找到。
其他替换只是为了避免文本中出现感叹号和插入符号的问题。
:::::::::::::::::::::::::::::::::::::::::::
:CountQuotes <stringVar> <result>
setlocal EnableDelayedExpansion
set "line=!%~1!"
set "#=+1"
rem DelayedExpansion: double all quotes
set "line=!line:"=""!"
rem DelayedExpansion: remove all carets ^
set "line=!line:^=!"
rem PercentExpansion: Remove all !
set "line=%line:!=%"
rem PercentExpansion: Replace double quotes to !!#:#=
set "line=-1^!#:#=%line:""=^!^!#:#=%"
for /F "delims=" %%X in ("!line!") do (
set /a count=%%X!
)
(
endlocal
set %~2=%count%
exit /b
)
添加线条和插入换行符的逻辑
@echo off
setlocal DisableDelayedExpansion
set "lastLine="
set LF=^
rem Two empty lines
for /F "delims=" %%A in (test.csv) do (
set "line=%%A"
setlocal EnableDelayedExpansion
set "line=!line:\=\x!"
if defined lastLine (
set "line=!lastLine!\n!line!"
)
call :CountQuotes line quoteCnt
set /a rest=quoteCnt %% 2
if !rest! == 0 (
for %%L in ("!LF!") DO set "line=!line:\n=%%~L!"
set "line=!line:\\=\!"
echo Complete Row: !Line!
echo(
set "lastLine="
) ELSE (
set "lastLine=!line!"
)
for /F "delims=" %%X in (""!lastLine!"") DO (
endlocal
set "lastLine=%%~X"
)
)
exit /b
:::::::::::::::::::::::::::::::::::::::::::
:CountQuotes <stringVar> <result>
setlocal EnableDelayedExpansion
set "line=!%~1!"
set "#=+1"
rem DelayedExpansion: double all quotes
set "line=!line:"=""!"
rem DelayedExpansion: remove all carets ^
set "line=!line:^=!"
rem PercentExpansion: Remove all !
set "line=%line:!=%"
rem PercentExpansion: Replace double quotes to !!#:#=
set "line=-1^!#:#=%line:""=^!^!#:#=%"
for /F "delims=" %%X in ("!line!") do (
set /a count=%%X!
)
(
endlocal
set %~2=%count%
exit /b
)
答案 1 :(得分:1)
下面的批处理文件可以执行您想要的操作:
@echo Off
setlocal EnableDelayedExpansion
call :processFile < test.csv
goto :EOF
:processFile
set line=
set /P line=
if not defined line exit /b
set "line=!line:,,=,@,!"
for %%a in (name sex age description mydate) do set %%a=
for %%a in (!line!) do (
if not defined name (
set "name=%%a"
) else if not defined sex (
set "sex=%%a"
) else if not defined age (
set "age=%%a"
) else if not defined description (
set "description=%%a"
) else if not defined mydate (
set "mydate=%%a"
)
)
:checkDate
if defined mydate goto show
set /P line=
for /F "tokens=1* delims=," %%a in ("!line!") do (
set "description=!description! %%a"
set "mydate=%%b"
)
goto checkDate
:show
for %%a in (name sex age description mydate) do set /P "=%%a=!%%a!, " < NUL
echo/
goto processFile
我添加了您在上一个主题中请求的要求,也就是说,性别可能是空的(并且由我在对该主题的回答中解释的@字符更改),并且名称可能包含逗号。我用这个数据文件测试了程序:
name,sex,age,description,date
venu,m,16,"test mesg",2012-05-01
test,,22,"He is good guy
and
brilliant",2012-05-01
"venu,gopal",m,16,"Another
multi-line
description",2012-05-02
得到这些结果:
name=name, sex=sex, age=age, description=description, mydate=date,
name=venu, sex=m, age=16, description="test mesg", mydate=2012-05-01,
name=test, sex=@, age=22, description="He is good guy and brilliant", mydate=2012-05-01,
name="venu,gopal", sex=m, age=16, description="Another multi-line description", mydate=2012-05-02,
请注意,任何包含逗号或空格的字段都必须用引号括起来。