批处理脚本 - 如何计算 CSV 或 TXT 文件中逗号的出现次数?

批处理脚本 - 如何计算 CSV 或 TXT 文件中逗号的出现次数?

我每天都要处理一堆 CSV 文件。它们具有固定格式,每个文件中都出现 19 个逗号。文件中混合了字符串、时间戳、整数和浮点数。文件始终以 CR-LF 集结尾。

每个文件只有一行文本,提供一组稍后处理的信息。

问题似乎是,负责生成该文件的设备有时会(每 1000 个文件一次)创建不完整的文件。缺少一些信息。

我需要将这些文件从所有好的文件中分离出来,然后再进一步处理它们。

在花费了大量时间尝试找出最可靠的解决方法后,我得出的结论是,由于文件不完整,因此缺少一些逗号。

所以我想计算一下 CSV 文件中出现的逗号数量。正确的文件应该有 19 个逗号,过去半年我发现的任何有问题的文件的逗号数量都比这个少。它们在行尾还缺少 CR-LF。它们只是在某个值后以逗号结尾,仅此而已。

良好 CSV 文件的示例:

STRING1,STRING2,2017-01-20 17:34:08,53.808536,-7.789231,19.5,3,0,STRING3,2017-01-20 17:34:19,2,0,7.9,2,0,1,0,0,0,0

错误的 CSV 文件示例:

STRING1,STRING3,2017-01-12 10:11:09,53.779093,-7.494274,

我的问题是:如何计算单个 CSV 文件中逗号的数量,如果这个数量与定义的数字不匹配,则执行某项操作(例如将这个不正确的文件移动到 ERRORS 文件夹中,我可以稍后处理)。如果文件中的逗号数量正确,那就让它保持原样。换句话说,我需要将格式不正确的 CSV 文件移动到 ERRORS 文件夹中,并将格式正确的 CSV 文件保留原样。

仅供参考:CSV 文件始终只有 1 行数据。

我尝试过某些解决方案,尝试在 TXT 文件中查找和计算某些字符串的实例,但毫无进展。可能是因为我的字符串只是一个逗号符号...我不知道。

我将非常感激您在此事上提供的帮助。

答案1

如何计算,CSV 文件中出现的次数?

使用以下批处理文件(CountCommas.cmd):

@echo off
setlocal EnableDelayedExpansion
set _comma=,
for /f "usebackq" %%a in (`dir /b /s *.csv`)  do (
  set _file=%%a
  set count=0
  for /f "usebackq tokens=*" %%b in (`type !_file!`) do (
    set _line=%%b
    call :count
  )
)
goto :done
:count
    if !_line:~0^,1! equ !_comma! (
      set /a count+=1
      )
    if "!_line:~1!" neq "" (
      set _line=!_line:~1!
      goto :count
      )
    echo file !_file! contains !count! commas
    if !count! neq 19 (
      echo error
      rem handle error here
      )
    )
:done
endlocal

笔记:

  • 替换rem handle error here为您的错误处理代码

使用示例:

> type bad.csv
STRING1,STRING3,2017-01-12 10:11:09,53.779093,-7.494274,
> type good.csv
STRING1,STRING2,2017-01-20 17:34:08,53.808536,-7.789231,19.5,3,0,STRING3,2017-01-20 17:34:19,2,0,7.9,2,0,1,0,0,0,0
> CountCommas
file F:\test\bad.csv contains 5 commas
error
file F:\test\good.csv contains 19 commas

进一步阅读

  • Windows CMD 命令行的 AZ 索引- 与 Windows cmd 行相关的所有事物的绝佳参考。
  • 目录- 显示文件和子文件夹的列表。
  • 对于/f- 循环命令以执行另一个命令的结果。
  • 如果- 有条件地执行命令。
  • - 显示、设置或删除 CMD 环境变量。使用 SET 所做的更改将仅在当前 CMD 会话期间保留。
  • 变量- 提取变量的一部分(子字符串)。

答案2

FINDSTR$正则表达式仅匹配 CR 之前的位置。因此,如果您的无效文件缺少 CR-LF,则可以使用以下一行将所有问题 csv 文件移动到错误文件夹。

for /f "eol=: delims=" %F in ('findstr /vm $ *.csv') do @move /y "%F" error >nul

如果将该命令放在批处理脚本中,则必须将百分比加倍。

@echo off
for /f "eol=: delims=" %%F in ('findstr /vm $ *.csv') do move /y "%%F" error >nul

如果愿意,您可以使用更复杂的正则表达式来查找不包含 19 个逗号的行:

@echo off
for /f "eol=: delims=" %%F in (
  'findstr /vm ".*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*," *.csv'
) do move /y "%%F" error >null

但简单地计算逗号可能并不可靠,因为引用的值也可能包含逗号,正如 LotPings 在他的回答中指出的那样。

答案3

问题应该是如何确保 csv 文件有 20 列/字段

假设文件中的字符串没有加引号并且不包含逗号,则此批处理将执行:

@Echo off&SetLocal EnableExtensions EnableDelayedExpansion
CD /d "X:\path\to\csv-folder"
Set Cnt=0
For %%A in (*.csv) Do Set File="%%A"&Set /P CSV=<%%A&Call :Count "!CSV:,=","!"
Goto :Eof
:Count
If "%~1" Neq "" Shift & Set /A Cnt+=1 & Goto :Count
If %Cnt% Neq 20 Echo %File% has %Cnt% Columns
Set "CSV="
Set Cnt=0

批处理将行括在双引号中,并用 替换每个逗号,,以便","将每个列括在引号中。所有这些都传递给子例程:Count,在该子例程中对参数进行计数并移动,直到不再存在参数。如果计数不同于 20,则 echo 发出错误消息。这可以用移动命令代替。

答案4

用批处理来计算文件中字符串字符的简单方法

您可以使用批处理脚本并在其中放入简单逻辑来创建动态 PowerShell 脚本来计算,逗号字符的数目,将计数设置为变量,并在批处理脚本逻辑中的其余处理操作中使用该变量。

PS 脚本不需要动态创建,您可以使用静态 PS 脚本。您可以将 PS 脚本的完整路径作为第一个参数传递给批处理脚本以供相应使用。

这很容易...完成...下一步!!

批处理脚本示例

ECHO ON

SET file=C:\folder\file.txt

CALL :CreatePSCommaCount
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0 
CD /D "%PowerShellDir%" 
FOR /F "DELIMS=" %%A IN ('Powershell -ExecutionPolicy Bypass -Command "& '%DynPSCommaCount%'"') DO SET "commacount=%%A"

IF NOT %commacount%==19 GOTO EOF
<other batch script logic below here since count is 19 (or whatever you need it to be)>
GOTO EOF

:CreatePSCommaCount
SET DynPSCommaCount=%Temp%\TempCommaCount.ps1
IF EXIST "%DynPSCommaCount%" DEL /Q /F "%DynPSCommaCount%"
ECHO $file  = GC "%file%"                                               >>"%DynPSCommaCount%"
ECHO $Match = Select-String -InputObject $file -Pattern "," -AllMatches >>"%DynPSCommaCount%"
ECHO $Match.Matches.Count                                               >>"%DynPSCommaCount%"
GOTO EOF

你会把一个简单的如果批处理脚本中的条件并使用移动如果文件与数字匹配或不匹配,则命令移动文件,但是您在现有的批处理脚本中拥有该逻辑。


更多资源

相关内容