如何计算 for /f 循环生成的标记数?

问题描述 投票:0回答:3

非常抱歉,如果已经有人提出并回答了这个问题。我浏览了类似标题的问题,但没有找到似乎适用于我的问题。另外,这是我在 Stack Overflow 上发布的第一个问题。

我有一个名为 sortcriteria.csv 的 csv 文件,目前包含 12 列和 5 行。

这里是csv文件的内容:

Private,ReadWriteInc,TheArts,Preschool,Transition,Staff,Music,Language,MultiYearOrGroups,MiddleYears,PhysicalActivity,StudentLeaders
PLT,RWI,Art,Pre,Tran,Staff,Uke,Language,Group,MiddleYears,PhysicalActivity,StudentLeaders
Personal,",",",",",Ukulele,Japanese,",",PE,"
Private,",",",",",Guitar,German,",",","
11 ,",",",",",Music,",",",","

这是 Excel 中的 csv 图片: picture of csv in Excel

如果我在分隔符设置为逗号的情况下通过

for /f
循环运行它,我可以获得 12 个标记,每列一个。 例如,以下代码将生成 12 个变量:

for /f "delims=, tokens=1-12" %%B in (C:\GAMWork\sortcriteria.csv) do ...

对于当前形式的 sortcriteria.csv,此

for
循环将迭代 5 次(每行一次),每次生成 12 个变量(
%%B
%%M
)。它会这样做,因为我已经告诉它有 12 列或标记,带有
"tokens=1-12"
.

但是,csv 文件可能并不总是有 12 列。将来可能会添加或减少列。 如何让批处理文件首先计算 csv 文件中的列数,然后使用该数字确定

for /f
循环查找的标记数?

我希望有以下内容:

<some code block that counts the number of columns in the csv file>

set /a tknnum=<Result from code block above>

for /f "delims=, tokens=1-%tknnum%" %%B in (C:\GAMWork\sortcriteria.csv) do ...

我特别希望我可以将列数设置为

tknnum
变量,因为我还需要在批处理文件的其他地方使用它用于其他目的。

我希望这个解释是清楚易懂的。

我没有任何尝试过的例子,因为我真的不知道从哪里开始尝试解决方案。 我想不出一种使用

for /f
来计算列数的 csv 文件的方法。 我已经从 Microsoft 的网站以及 ss64.com 阅读了
for
命令的文档。 如前所述,我还在 Stack Overflow 上搜索了类似标题的其他问题。在我能理解的那些中,似乎没有一个适用于我的上下文。 我能找到的最接近的是这个:https://stackoverflow.com/a/72903742/,但是我在试图理解@Magoo 的回答时迷路了。

编辑:我意识到使用

"
作为空白单元格的填充物是一个坏主意。对不起

windows csv for-loop batch-file cmd
3个回答
1
投票

到目前为止回答你的问题:
通过仅计算元素来获取列数(使用第一行,即标题)(注意:这使用标准分隔符(不可更改),因此如果列中应该有空格,则必须引用该值(像

"Student Leaders"
.

@echo off
<sortcriteria.csv set /p header=
set columns=0
for %%a in (%header%) do set /a columns+=1
echo Your file has %columns% columns.
for /f "tokens=1-%columns% delims=," %%a in (sortcriteria.csv) do ...

悬而未决的问题:你仍然不知道哪个字母是你的最后一个标记。可能有更好的解决方案。你到底想做什么?


1
投票

构建带逗号和不带逗号的行的长度差异。

setlocal EnableDelayedExpansion
set /p firstLine= < file.csv
call :strlen firstLine totalLength
set "reduced=!firstLine:,=!"
call :strlen firstLine LengthWithoutCommas

set /a tknnum=totalLength-LengthWithoutCommas+1
echo %tknum%
exit /b

:strlen <stringVar> <resultVar>
(   
    setlocal EnableDelayedExpansion
    (set^ tmp=!%~1!)
    if defined tmp (
        set "len=1"
        for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
            if "!tmp:~%%P,1!" NEQ "" ( 
                set /a "len+=%%P"
                set "tmp=!tmp:~%%P!"
            )
        )
    ) ELSE (
        set len=0
    )
)
( 
    endlocal
    set "%~2=%len%"
    exit /b
)

链接到批处理字符串长度函数
宏批量字符串长度函数

但是正如@Stephan 已经提到的那样,计数可能帮助不大。

这是一个为每一行构建一个数组的解决方案

@echo off
setlocal EnableDelayedExpansion
(set LF=^
%=empty=%
)


set lineNumber=0

for /f "delims=" %%B in (%filename%) DO (
  set /a lineNumber+=1
  set count=0
  set "CSV=%%B"
  echo [!lineNumber!]: !CSV!
  for %%L in ("!LF!") do set "CSV=!CSV:,=%%~L!"
  FOR /F "tokens=* delims=" %%a in ("!CSV!") DO (
    set /a count+=1
    echo   Column[!count!]: "%%a"
    set "content[!line!][!column!]=%%a"
  )
)

0
投票

这是另一种,也许更简单的方法:

@echo off

set /P "header=" < sortcriteria.csv
set tokens=1 & set "col=%header:,=" & set /A tokens+=1 & set "col=%"
echo Tokens=%tokens%

此方法将指定字符精确作为分隔符(在本例中为逗号,与

for /F
命令相同),因此您可以在列中插入空格或制表符。

如果你不知道你的文件有多少列,你就不知道使用了哪些字母标记。下面的程序将字母标记转换为数组元素,因此您可以通过其下标使用任何数组元素和/或将元素的处理限制为下标不大于标记的元素:

@echo off
setlocal EnableDelayedExpansion

rem Count the tokens in file
set /P "header=" < sortcriteria.csv
set tokens=1 & set "col=%header:,=" & set /A tokens+=1 & set "col=%"
echo Tokens=%tokens%

rem Define the conversion from tokens to array elements
set "letter= abcdefghijklmnopqrstuvwxyz"
set "TokensToArray="
for /L %%i in (1,1,%tokens%) do (
   set "TokensToArray=!TokensToArray!& set "array[%%i]=%%!letter:~%%i,1!" "
)
set "TokensToArray=!TokensToArray:~1!"

rem Process the file
for /F "tokens=1-%tokens% delims=," %%a in (sortcriteria.csv) do (
   %TokensToArray%
   echo -------------------------
   echo Column 1 = "!array[1]!"
   echo Column 7 = "!array[7]!"
)

输出:

Tokens=12
-------------------------
Column 1 = "Private"
Column 7 = "Music"
-------------------------
Column 1 = "PLT"
Column 7 = "Uke"
-------------------------
Column 1 = "Personal"
Column 7 = "Ukulele"
-------------------------
Column 1 = "Private"
Column 7 = "Guitar"
-------------------------
Column 1 = "11 "
Column 7 = "Music"
© www.soinside.com 2019 - 2024. All rights reserved.