我有這個 .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 列,其結構與之前的列相同。
uj5u.com熱心網友回復:
@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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/438167.html
標籤:windows csv batch-file
