我有一个.csv文件:
col0,col1,col2,col3,col4
a,1,10,100,1000
b,2,11,101,1001
c,3,12,102,1002
d,4,13,103,1003
e,5,14,105,1004我需要在不知道列数的情况下迭代.csv中的每个列。跳过第一列是因为不需要。到目前为止,我有这段代码,但是我需要一个解决方案,以解决我不知道列数的情况。在后面的步骤中,我需要每个列的值,其中我计算了一些内容。
@echo off
setlocal enableDelayedExpansion
:: set workspace data
set INPUT_FILE_LOCATION=D:\Scripts\
set CSV_FILE_NAME=test.csv
pushd %INPUT_FILE_LOCATION%
::loop through the csv file
for /F "tokens=2,3,4,5 delims=," %%i in (%CSV_FILE_NAME%) do (
echo %%i,%%j,%%k,%%l
rem echo.%%~i^|END
)
endlocal 更确切地说,我有一个.csv文件,包含一些列和许多行。从第二列开始,我将需要对每一列的每两个元素进行差分,以验证是否至少存在一个大于1的差异。(列上的值将按升序排列,因此使用上面的csv,代码应该执行以下操作:从col1开始,验证如果2-1 > 1,然后如果3-2 > 1,如果4-3 >1那么5-4 > 1,那么它应该验证下一列(Col2)的相同内容,等等,直到我们到达最后一列为止。如果我将发现一个大于1的差异,我想打印一条消息,即“在该列的标题上发现了更大的差异”,其中发现了较大的差异;我想通过使用标题中的列标题来定位哪一列中发现了意外的差异;例如,在col3中,我们的差异大于1,我想打印“col3中有大于1的差异”,其中col3位于标头中)。随着时间的推移,我将需要添加更多的列,因此文件可以有30或40列,其结构与前面的列相同。
发布于 2022-03-01 19:30:04
@ECHO OFF
SETLOCAL
rem The following settings for the source directory, filenames are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "filename1=%sourcedir%\q71308045.txt"
:: comma-separated list of columns to ignore
SET "ignorecolumns=1"
:: remove all 'cell' variables from environment
For %%b IN (cell) DO FOR /F "delims==" %%c In ('set %%b 2^>Nul') DO SET "%%c="
SET /a rowcount=0
SET /a maxcolumns=0
rem usebackq should be omitted if the source filename is not quoted
rem skip=1 skips the first (header) line. Omit to skip no lines
FOR /f "usebackq skip=1 delims=" %%b IN ("%filename1%") DO (
CALL :process %%b
CALL :linebyline
)
ECHO %rowcount% rows, maximum %maxcolumns% columns
SET cell
GOTO :EOF
:process
SET /a rowcount+=1
SET /a columns=0
:procloop
IF "%~1"=="" GOTO :eof
SET /a columns+=1
IF DEFINED ignorecolumns FOR %%c IN (%ignorecolumns%) DO IF %columns%==%%c GOTO donecolumn
SET "cell[%rowcount%,%columns%]=%~1"
:donecolumn
IF %columns% gtr %maxcolumns% SET /a maxcolumns=columns
SET /a cellsinrow[%rowcount%]=%columns%
SHIFT
GOTO procloop
GOTO :eof
:: processing line-by-line if required
:linebyline
ECHO row %rowcount% has %columns% columns
GOTO :eof在没有具体细节的情况下,这里有一个通用的解决方案。
请注意,它不适合空列。
每一行都作为参数呈现给:process。:process对每一列进行计数,并将其插入到cells有线数组中,省略任何不需要的列,并跟踪找到的最大列数和每行中的单元格数。
AFAIAA的环境空间有限,因此在处理大量数据时需要采取补偿措施。
对每一行执行:linebyline例程,因此如果所需的处理不需要cells,则可以在此例程中将rowcount设置为0,对每一行都具有报告cells[1,*]的效果。
-澄清后的修订
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory, filenames are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "filename1=%sourcedir%\q71308045.txt"
:: comma-separated list of columns to ignore
SET "ignorecolumns=1"
:: remove all 'cell' variables from environment
For %%b IN (cell) DO FOR /F "delims==" %%c In ('set %%b 2^>Nul') DO SET "%%c="
SET /a rowcount=0
SET /a maxcolumns=0
rem usebackq should be omitted if the source filename is not quoted
rem skip=1 skips the first (header) line. Omit to skip no lines
FOR /f "usebackq delims=" %%b IN ("%filename1%") DO (
CALL :process %%b
CALL :linebyline
)
rem ECHO %rowcount% rows, maximum %maxcolumns% columns
rem SET cell
GOTO :EOF
:process
SET /a rowcount+=1
SET /a columns=0
:procloop
IF "%~1"=="" GOTO :eof
SET /a columns+=1
IF DEFINED ignorecolumns FOR %%c IN (%ignorecolumns%) DO IF %columns%==%%c GOTO donecolumn
SET "cell[%rowcount%,%columns%]=%~1"
:donecolumn
IF %columns% gtr %maxcolumns% SET /a maxcolumns=columns
SET /a cellsinrow[%rowcount%]=%columns%
SHIFT
GOTO procloop
GOTO :eof
:: processing line-by-line if required
:linebyline
:: if rowcount=1 then column names are in cell[1,*] and nothing to do
:: if rowcount=2 then we have the starting data row and nothing to do
IF %rowcount% lss 3 GOTO :eof
:: Now we can compare row 2 to row %rowcount%
FOR /L %%c IN (1,1,%maxcolumns%) DO IF "!cell[2,%%c]!" neq "" CALL :matchcells %%c
:: And move row %rowcount% to row 2; removing row %rowcount% from environment
FOR /L %%c IN (1,1,%maxcolumns%) DO IF "!cell[2,%%c]!" neq "" SET cell[2,%%c]=!cell[%rowcount%,%%c]!&SET "cell[%rowcount%,%%c]="
GOTO :eof
:: Match cell[2,%1] to cell[%rowcount%,%1]
:matchcells
SET /a celldiff = !cell[%rowcount%,%1]! - !cell[2,%1]!
IF %celldiff% == 1 GOTO :eof
ECHO row %rowcount% column %1 [!cell[1,%1]!] value difference = %celldiff%
GOTO :eof嗯,这里没什么区别。我仍然认为该规范是错误的,因为如果您知道第一个数据行,那么您就知道接下来的每个数据行应该是什么,因为下一个行中的每个列都应该比前面行中的值多一个。因此,您只需要一行数据,因为您可以生成其余的行,而不需要经过生成/验证循环。
https://stackoverflow.com/questions/71308045
复制相似问题