1

这是对另一个问题的扩展(循环通过带有批处理的 CSV 文件 - 空间问题

我有这样的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 条记录。

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

4

2 回答 2

2

主要问题似乎是计算一行中的引号。
如果引号的数量是奇数,那么您需要附加下一行并再次计算引号。

如果您不遍历所有字符,则对字符串中的字符进行计数有点棘手。
我在这里使用了延迟缩减技术,每个引号将被有效地替换为 a+1并且所有其他字符都被删除。
为了以正确的方式开始和终止行,开头总是有一个额外+1的,这将由-1前面的 a 补偿。

主要技巧是+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
)
于 2012-06-05T11:35:27.847 回答
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,

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

于 2012-05-24T03:01:16.033 回答