用批处理替换 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 文件中的列值的主要内容,如果未能解决你的问题,请参考以下文章

将给定 .csv 文件中的现有值替换为 NAN

更改 bigquery 中的列值

批处理文件复制 CSV 文件中的列

Oracle SQL REGEXP 用不同的列值替换特定字符串

powershell 在CSV文件中查找重复的列值

使用 pyspark 处理 csv 文件中字段中的逗号