Batch file 批处理:将.csv转换为制表符分隔的文本,仅引用部分字段,引号之间包含逗号(易趣订单文件)

Batch file 批处理:将.csv转换为制表符分隔的文本,仅引用部分字段,引号之间包含逗号(易趣订单文件),batch-file,csv,comma,tab-delimited,quotation-marks,Batch File,Csv,Comma,Tab Delimited,Quotation Marks,我正在尝试将易趣文件交换下载转换为发货软件可以读取的制表符分隔格式 如果每一列都被引用,这将很容易——但事实并非如此。只有一些列(名称、项目列表标题等)被引用,而一些被引用的列包含逗号。其余的都没有引用 我需要一种在.bat文件中解析和转换它的方法,但是如果引用的字段也包含逗号,则使用逗号作为分隔符会分割这些字段,从而产生无法使用的数据。我肯定有一个简单的解决方法,我就是想不出来。还有一个更复杂的问题:带有引号和逗号的字段也会转义引号: 小吉姆·史密斯 将在CSV文件中表示为 小吉姆·斯密蒂·史

我正在尝试将易趣文件交换下载转换为发货软件可以读取的制表符分隔格式

如果每一列都被引用,这将很容易——但事实并非如此。只有一些列(名称、项目列表标题等)被引用,而一些被引用的列包含逗号。其余的都没有引用


我需要一种在.bat文件中解析和转换它的方法,但是如果引用的字段也包含逗号,则使用逗号作为分隔符会分割这些字段,从而产生无法使用的数据。我肯定有一个简单的解决方法,我就是想不出来。

还有一个更复杂的问题:带有引号和逗号的字段也会转义引号:

小吉姆·史密斯

将在CSV文件中表示为

小吉姆·斯密蒂·史密斯

这不是在批处理文件中容易解决的问题。但是,已有处理CSV格式的功能,可以从任何与.NET兼容的语言使用,包括。如果这是一个选项,请查看

有关调用.NET方法从Powershell读取CSV文件的信息,请参阅


还有一个更复杂的问题:带有引号和逗号的字段也将转义引号:

小吉姆·史密斯

将在CSV文件中表示为

小吉姆·斯密蒂·史密斯

这不是在批处理文件中容易解决的问题。但是,已有处理CSV格式的功能,可以从任何与.NET兼容的语言使用,包括。如果这是一个选项,请查看

有关调用.NET方法从Powershell读取CSV文件的信息,请参阅


还有一个更复杂的问题:带有引号和逗号的字段也将转义引号:

小吉姆·史密斯

将在CSV文件中表示为

小吉姆·斯密蒂·史密斯

这不是在批处理文件中容易解决的问题。但是,已有处理CSV格式的功能,可以从任何与.NET兼容的语言使用,包括。如果这是一个选项,请查看

有关调用.NET方法从Powershell读取CSV文件的信息,请参阅


还有一个更复杂的问题:带有引号和逗号的字段也将转义引号:

小吉姆·史密斯

将在CSV文件中表示为

小吉姆·斯密蒂·史密斯

这不是在批处理文件中容易解决的问题。但是,已有处理CSV格式的功能,可以从任何与.NET兼容的语言使用,包括。如果这是一个选项,请查看

有关调用.NET方法从Powershell读取CSV文件的信息,请参阅


Eric J是正确的-用批处理解决此类问题并不简单。但这是可能的:-)

主要的问题是如何区分带引号和不带引号的逗号-jeb解决了带引号和不带引号分号的类似问题。下面的代码看起来非常不同,但基本概念是相同的

下面的代码应该适用于几乎任何CSV,只要所有行的长度小于~8000字节。批处理变量值限制为8191字节,某些字符临时扩展为两个字节

代码假定CSV文件中没有任何现有选项卡

它不会修改任何现有的引号

正如我所说,代码应该可以工作,但是如果您有一个大文件,那么它的速度会非常慢。按照Eric J的建议,使用.NET解决方案会更好

@echo off
setlocal disableDelayedExpansion

set "file=optionalPathinfo\yourFile.csv"

:: Define a TAB variable
for /f "delims=" %%A in (
  'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x09"'
) do set "TAB=%%A"


:: Read each line from CSV, convert it, and write to new file with .new extension
>"%file%.new" (
  for /f usebackq^ delims^=^ eol^= %%A in ("%file%") do (
    set "line=%%A"
    call :processLine
  )
)
exit /b


:processLine
setlocal enableDelayedExpansion

:: Protect problem characters
set "line=!line:@=@A!"
set "line=!line:^=@K!"
set "line=!line:&=@M!"
set "line=!line:|=@P!"
set "line=!line:<=@L!"
set "line=!line:>=@G!"

:: Mark commas with leading caret (escape)
set "line=!line:,=^,!"

:: Remove mark from unquoted commas, but first temporarily
:: disable delayed expansion to protect any ! characters
setlocal disableDelayedExpansion
set ^"line=%line%"
setlocal enableDelayedExpansion

:: Protect remaining marked commas
set "line=!line:^,=@C!"

:: Convert remaining commas to TAB
set "line=!line:,=%TAB%!"

:: Restore protected characters
set "line=!line:@C=,!"
set "line=!line:@G=>!"
set "line=!line:@L=<!"
set "line=!line:@P=|!"
set "line=!line:@M=&!"
set "line=!line:@K=^!"
set "line=!line:@A=@!"

:: Write modified line
echo(!line!
exit /b
@echo关闭
setlocal disableDelayedExpansion
设置“file=optionalPathinfo\yourFile.csv”
::定义选项卡变量
对于/f“delims=”%%A in(
'forfiles/p“%~dp0.”/m“%~nx0”/c”cmd/c echo(0x09“'
)是否设置“TAB=%%A”
::从CSV中读取每一行,将其转换,然后写入扩展名为.new的新文件
>%file%.new(
对于/f usebackq^delims^=^eol^=%%A in(“%file%”)do(
设置“行=%%A”
呼叫:processLine
)
)
退出/b
:进程线
setlocal enableDelayedExpansion
::保护问题字符
设置“line=!line:@=@A!”
设置“line=!line:^=@K!”
设置“line=!line:&=@M!”
设置“行=!行:|=@P!”
设置“line=!line:=@G!”
::用前导插入符号标记逗号(转义)
设置“行=!行:,=^,!”
::从未加引号的逗号中删除标记,但先暂时删除
::禁用延迟扩展以保护任何!个字符
setlocal disableDelayedExpansion
设置^“行=%line%”
setlocal enableDelayedExpansion
::保护剩余的标记逗号
设置“line=!line:^,=@C!”
::将剩余逗号转换为制表符
设置“行=!行:,=%TAB%!”
::还原受保护的字符
设置“行=!行:@C=,!”
设置“line=!line:@G=>!”

设置“line=!line:@L=Eric J是正确的-用批处理解决此类问题并不简单。但它是可能的:-)

主要的问题是如何区分带引号和不带引号的逗号-jeb在解决了带引号和不带引号的分号的类似问题。下面的代码看起来非常不同,但基本概念是相同的

下面的代码应该适用于几乎任何CSV,只要所有行的长度小于~8000字节。批处理变量值限制为8191字节,并且一些字符临时扩展为两个字节

代码假定CSV文件中没有任何现有选项卡

它不会修改任何现有的引号

正如我所说,代码应该可以工作,但是如果你有一个大文件,那么它的速度会非常慢

@echo off
setlocal disableDelayedExpansion

set "file=optionalPathinfo\yourFile.csv"

:: Define a TAB variable
for /f "delims=" %%A in (
  'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x09"'
) do set "TAB=%%A"


:: Read each line from CSV, convert it, and write to new file with .new extension
>"%file%.new" (
  for /f usebackq^ delims^=^ eol^= %%A in ("%file%") do (
    set "line=%%A"
    call :processLine
  )
)
exit /b


:processLine
setlocal enableDelayedExpansion

:: Protect problem characters
set "line=!line:@=@A!"
set "line=!line:^=@K!"
set "line=!line:&=@M!"
set "line=!line:|=@P!"
set "line=!line:<=@L!"
set "line=!line:>=@G!"

:: Mark commas with leading caret (escape)
set "line=!line:,=^,!"

:: Remove mark from unquoted commas, but first temporarily
:: disable delayed expansion to protect any ! characters
setlocal disableDelayedExpansion
set ^"line=%line%"
setlocal enableDelayedExpansion

:: Protect remaining marked commas
set "line=!line:^,=@C!"

:: Convert remaining commas to TAB
set "line=!line:,=%TAB%!"

:: Restore protected characters
set "line=!line:@C=,!"
set "line=!line:@G=>!"
set "line=!line:@L=<!"
set "line=!line:@P=|!"
set "line=!line:@M=&!"
set "line=!line:@K=^!"
set "line=!line:@A=@!"

:: Write modified line
echo(!line!
exit /b
@echo关闭
setlocal disableDelayedExpansion
设置“file=optionalPathinfo\yourFile.csv”
::定义选项卡变量
对于/f“delims=”%%A in(
“forfiles/p”%~dp0