循环访问具有批处理中断问题的CSV文件

时间:2012-05-23 06:54:49

标签: windows batch-file cmd

这是另一个问题(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条记录。

如何解决这个问题?提前谢谢。

2 个答案:

答案 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,

请注意,任何包含逗号或空格的字段都必须用引号括起来。