用批处理替换 csv 文件中的列值
Posted
技术标签:
【中文标题】用批处理替换 csv 文件中的列值【英文标题】:Replace column values from a csv file with batch 【发布时间】:2021-10-14 23:02:40 【问题描述】:我有一个逗号分隔的 csv 文件,如下所示:
ID,USER_ID, COL3_STR, COL4_INT
id1,username1,exampleA, 5
id2,username1,exampleB,0
id3,username2,NULL,-1
id4,username3,,3,false,20
第二列 USER_ID 中的每个值都必须替换为 testusername(标题“USER_ID”除外)。值不同,所以我无法搜索已定义的字符串。
我的想法是使用 for 循环并从每一行获取第二个令牌以获取用户名。例如:
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET currentDir=%~dp0
SET "srcfile=%currentDir%\inputfile.csv"
SET "outfile=%currentDir%\result.csv"
for /f "tokens=2 delims=," %%A IN (%srcfile%) DO (
ECHO %%A)
ECHO done
PAUSE
输出:
USER_ID
username1
username1
username2
username3
因此(新)csv 文件的第二列必须如下所示:
USER_ID
testusername
testusername
testusername
testusername
我看到another question 和一个有用的answer。 示例:当每个用户名都是“admin”时:
(
for /f "delims=" %%A in (%srcfile%) do (
set "line=%%A"
for /f "tokens=2 delims=," %%B in ("admin") do set "line=!line:%%B=testuser!"
echo !line!
)
)>%outfile%
但这仅适用于已定义的字符串。这是我的第一个批处理脚本,我不知道如何根据我的情况“组合”它。我希望有人能帮助我。 必须适用于 Windows 7 和 10。
【问题讨论】:
"admin"
中没有第二个令牌,因此没有任何内容被替换。当您将"admin"
替换为"%%A"
时,它可能会起作用。但另一方面,您不需要提取用户名 - 无论如何都将其丢弃(请参阅我的答案以获得更直接的解决方案)。
【参考方案1】:
您需要所有令牌(用于写入修改后的文件),而不仅仅是第二个:
for /f "tokens=1,2,* delims=," %%A in (%srcfile%) do echo %%A,testuser,%%C
(其中*
是“行的其余部分,未定界”)。 %%B
将是用户名,因此只需编写替换字符串即可。
您可以使用if
语句以不同方式处理第一行,或者单独处理:
<"%srcfile%" set /p header=
(
echo %header%
for /f "skip=1 tokens=1,2,* delims=," %%A in (%srcfile%) do echo %%A,testuser,%%C
) > "%outfile%"
【讨论】:
嘿,非常感谢您(再次)的帮助,也感谢您的评论,这有助于我理解。有用。但是我还有另一个问题:我在命令行中获取每个第一列的值,并显示以下消息(已翻译):“命令 'id1' 拼写错误或找不到”。我怎样才能防止这种情况发生? 不会发生在我身上。你在任何地方都使用%%A
而不使用echo
吗?另一个可能的原因:srcfile
未编码为 ANSI 和/或具有非 Windows 行尾。【参考方案2】:
以下脚本(我们称之为 repl_2nd.bat
)替换 CSV 文件第二列中的值并正确处理空字段(其中分隔符彼此相邻,如 ,,
):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=%~1" & rem // (path to input file; `%~1` is first argument)
set "_NVAL=testusername" & rem // (new string for second column)
set "_SEPC=," & rem // (separator character usually `,`)
rem // Especially handle first line:
< "%_FILE%" (
set "HEAD=" & set /P HEAD=""
setlocal EnableDelayedExpansion
echo(!HEAD!
endlocal
)
rem // Read input file line by line:
for /F usebackq^ skip^=1^ delims^=^ eol^= %%L in ("%_FILE%") do (
rem // Store current line string:
set "LINE=%%L"
rem // Toggle delayed expansion to avoid loss of `!`:
setlocal EnableDelayedExpansion
rem /* Replace each separator `,` by `","` and enclose whole line string in `""`,
rem resulting in all items to become quoted, ven empty ones, hence avoiding
rem adjacent separators, which would become collapsed to one by `for /F`;
rem then split the edited line string at the first and second separators: */
for /F "tokens=1,2,* delims=%_SEPC% eol=%_SEPC%" %%A in (^""!LINE:%_SEPC%="^%_SEPC%"!"^") do (
rem /* Unquote the first item, then join a separator and the replacement string;
rem then remove the outer pair of quotes from the remaining line string: */
endlocal & set "REPL=%%~A%_SEPC%%_NVAL%" & set "REST=%%~C"
rem // Append the remaining line string with `","` replaced by separators `,`:
setlocal EnableDelayedExpansion & echo(!REPL!%_SEPC%!REST:"%_SEPC%"=%_SEPC%!
)
endlocal
)
endlocal
exit /B
要对当前工作目录中的文件使用脚本,请使用以下命令行:
repl_2nd.bat "inputfile.csv"
要将输出存储到另一个文件,请使用以下命令行:
repl_2nd.bat "inputfile.csv" > "outputfile.csv"
【讨论】:
以上是关于用批处理替换 csv 文件中的列值的主要内容,如果未能解决你的问题,请参考以下文章