我使用VBA从XLS文件生成CSV,之后我使用Batch过滤CSV。我的过滤器如下所示:
for %%a in (*.csv) do (
for /f "usebackq tokens=1-10 delims=, eol=^" %%1 in ("%%a") do (
if %%4 EQU Req_Category ECHO %%1,%%2,%%3,%%4,%%5,%%6,%%7,%%8,%%9 >> "%%a"_JIRA.csv
if %%4 EQU Requirement ECHO %%1,%%2,%%3,%%4,%%5,%%6,%%7,%%8,%%9 >> "%%a"_JIRA.csv
)
)
如果CSV文件没有空行,这可以正常工作。 在极少数情况下XLS - > CSV转换会在CSV中生成空行或CR。
SW_Fn-289,4.1.1.1,Controling Hardware PCB,Heading,,,,,IgnoreTesting,
SW_Fn-291,4.1.1.1.0-1,"
Date : 07.03.1777
The SystemDesignSpecification is stored in SVN path
http://sblablablabla.xlsm
",Requirement,Lab1 (B-Sample),,Released,Accepted,IgnoreTesting,
SW_Fn-4281,4.1.1.1.0-2,"
Date : 123.123.123
Path : https://apath.com
",Requirement,R1,,New,New,IgnoreTesting,
SW_Fn-166,4.2,Compliance Requirements,Heading,,,,,IgnoreTesting,
SW_Fn-286,4.2.1,Resource Usage,Heading,,,,,IgnoreTesting,
CSV中的每一行都应以ID开头:SW_Fn-Example。 是否每个人都知道如何使用批处理功能将信息带到一行?
我需要让文件看起来像这样(在过滤之前):
SW_Fn-289,4.1.1.1,Controling Hardware PCB,Heading,,,,,IgnoreTesting,
SW_Fn-291,4.1.1.1.0-1,"Date : 07.03.1777 TheSystemDesignSpecificationisstored in SVN path http://sblablablabla.xlsm",Requirement,Lab1 (B-Sample),,Released,Accepted,IgnoreTesting,
SW_Fn-4281,4.1.1.1.0-2," Date : 123.123.123 Path : https://apath.com",Requirement,R1,,New,New,IgnoreTesting,
SW_Fn-166,4.2,Compliance Requirements,Heading,,,,,IgnoreTesting,
SW_Fn-286,4.2.1,Resource Usage,Heading,,,,,IgnoreTesting,
不应该有一条不以SW_Fn-blabla开头的行。如果一行以其他内容开头,那么它应该是前一行中具有Sw_Fn-blabla的一部分。
然后我的过滤器会产生这个:
SW_Fn-291,4.1.1.1.0-1,"Date : 07.03.1777 TheSystemDesignSpecificationisstored in SVN path http://sblablablabla.xlsm",Requirement,Lab1 (B-Sample),,Released,Accepted,IgnoreTesting,
SW_Fn-4281,4.1.1.1.0-2," Date : 123.123.123 Path : https://apath.com",Requirement,R1,,New,New,IgnoreTesting,
提前致谢
答案 0 :(得分:0)
AAK!不要在metavariable
(%%1
)使用数字 - 它非常不可靠。使用字母字符。
Batch将一个分隔符字符串视为单个分隔符,并且您已指定逗号和空格作为分隔符,因此
SW_Fn-166,4.2,Compliance Requirements,Heading,,,,,IgnoreTesting,
将显示为
SW_Fn-166,4.2,Compliance,Requirements,Heading,IgnoreTesting,,,,
您还没有表现出您对输出的期望。您是否只想要开始SW_Fn-
的行,或者您是否希望所有不开始SW-Fn
的行都附加到最后一行?
@ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q36475816.csv"
SET "outfile=%destdir%\outfile.txt"
SET "line="
(
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
SET "newpart=%%a"
IF DEFINED line CALL :test
IF DEFINED line CALL SET "line=%%line%% %%a"
IF NOT DEFINED line SET "line=%%a"
)
IF DEFINED line ECHO(%line%
)>"%outfile%"
GOTO :EOF
:: Test new data " Accumulate data into line or output & start a new line
:test
SET "newpart=%newpart:"=x%"
IF NOT "%newpart:~0,6%"=="SW_Fn-" goto :eof
echo(%line%
SET "line="
GOTO :eof
您需要更改sourcedir
和destdir
的设置以适合您的具体情况。
我使用了一个名为q36475816.csv
的文件,其中包含我的测试数据。
生成定义为%outfile%
的文件请注意,您发布的数据包含Fn-4281
项中的不平衡报价。使用实际数据总是比使用实际数据更好,而不是'#34;某处接近"
阅读每一行。如果我们已经累积了一行的一部分,请检查前几个字符是否是目标。如果是,则输出构造的行并清除line
。
如果此操作后line
清零,请将其设置为读取的行(必须从目标开始,否则累积该行。
在:test
过程中,在测试之前删除引号,以便它不会破坏语法。显然,如果前几个字符包含引号,则它不适合目标,因此测试将正确检测"no fit"
答案 1 :(得分:0)
试试这个:
@echo off
for %%a in (*.csv) do (
for /f "delims=" %%b in (%%a) do (
for /f "tokens=4 delims=," %%c in ("%%b") do (
if "%%c"=="Requirement" echo %%b >>%%~na_JIRA%%~xa
if "%%c"=="Req_Category" echo %%b >>%%~na_JIRA%%~xa
)
)
)
读取并处理每一行完成以克服Magoo提到的连续分隔符问题(使用另一个for
来检查Token4,但不要费心拆解和重新组装整行)
答案 2 :(得分:0)
您的文件实际上是有效的CSV格式。带引号的CSV字段可能包含以下任何内容:
""
您的字段中没有逗号或引号,但您确实有新行代码会给您的代码带来严重问题。
但这只是一个潜在的问题。另一个问题是FOR / F将连续分隔符视为单个分隔符,因此如果您所需的任何守护线都有任何空字段,那么您的输出将完全错误。
对于任何类型的文本处理来说,批处理本质上远非理想,但对于CSV,除了最简单的问题之外,其他所有问题都特别糟糕。如果您确实想要使用批处理,可以使用ParseCSV.bat正确解析CSV并以可靠的方式使用FOR / F读取它。但是有更好的选择。 PowerShell有一个Import-Csv
cmdlet。我不确定它的功能,但是如果它支持字段中的换行,那么你可以开发一个非常灵活的解决方案。
另一个选项是JREPL.BAT regular expression text processor。以下代码看起来很讨厌,但它会在一步中非常高效地生成所需的输出:
jrepl "((?:[\s\S]*?,){3}(?:(Req_Category,|Requirement,)|.*?,)(?:.*?,){4}.*?),[^,\n]*\n?" "$2?$1.replace(/\r\n/g,' ')+'\r\n':''" /m /j /f input.csv /o output.csv
如果将命令放在另一个批处理脚本中,则需要使用CALL JREPL。
我的JREPL解决方案依赖于以下事实:您的输入字段都不包含带引号的逗号。如果它确实包含带引号的逗号,那么JREPL解决方案将更加复杂。
此解决方案使用/ M多行选项,以便我可以跨换行符匹配。
搜索匹配每个10个字段集合(您的第10个字段似乎始终为空),无论换行符如何。 $ 1包含前9个字段(不带尾随逗号)。当且仅当它与“Req_Category”或“Requirement”匹配时,$ 2包含第4个字段。替换的javascript表达式测试是否定义了$ 2,如果是,则在用空格替换所有换行符之后将整个搜索表达式替换为$ 1,然后追加换行符。如果未定义$ 2,则整个搜索表达式将替换为空字符串。简单的概念,但有点讨厌开发; - )
略微简化允许您保留包含换行符的原始字段,并且仍然可以进行所需的过滤。:
jrepl "((?:[\s\S]*?,){3}(?:(Req_Category,|Requirement,)|.*?,)(?:.*?,){4}.*?),[^,\n]*\n?" "$2?$1+'\r\n':''" /m /j /f input.csv /o output.csv