1

我在 Windows 批处理文件中的字符串引号有一些问题。我尝试解析 csv 文件(分隔)和多行条目。我必须仅将第四个操作符之后的字符串写出作为文本文件。结果必须包括新行和引号。

输入:

"1","50","1","Warning! Q1: Value too high [W-0001]"
"2","49","1","Warning! Q1: Value too low [W-0002]"
"3","48","1","Warning! Q1: Value changing too fast.
Check for endless loop[W-0003]"

输出:

 "Warning! Q1: Value too high [W-0001]"
 "Warning! Q1: Value too low [W-0002]" 
 "Warning! Q1: Value changing too fast.
 Check for endless loop[W-0003]"

这适用于没有新行的字符串。

for /F "tokens=1-4 skip=4 delims=," %%a in (input.csv) do @echo %%d >> output.txt

我试过了,但出现语法错误

for /F "delims=, tokens=1-4" %%a in (input.csv) do call :loopbody %%a %%b %%c %%d
goto :eof

if [%4]==[] goto :test
echo %4
goto :eof

:test
echo %1

由于字符串开头的引号而出错

Syntaxfehler.
C:\>if ["Warning Value changing too fast.]==[] goto :test

如何处理带引号的变量值?

4

2 回答 2

3

这适用于您的数据:

@echo off
for /F "delims=, tokens=1-3,*" %%a in (input.csv) do (
set "aa="
set "aa=%%d"
   if not defined aa (
        >>file.out echo %%a
     ) else (
        >>file.out echo %%d
   )
)
于 2013-09-26T00:37:58.793 回答
1

正则表达式是美妙的东西 :) 您可以使用名为 REPL.BAT 的混合 JScript/批处理实用程序,它在标准输入上执行正则表达式搜索和替换,并将结果写入标准输出。

假设 REPL.BAT 在您的当前目录中,或者更好的是,在您的路径中的某个地方,那么以下一个衬里直接从命令行工作:

repl "^(?:[^,]*,){3}(\q[^\q]*\q).*$" "$1\n" mx <input.csv >output.txt

请注意,上述解决方案假设每条记录至少包含 4 列(3 个逗号)。它还假设前 3 列的值中不包含任何逗号,第 4 列必须被引用并且不能包含转义的引号"",并且第 4 列之后的任何列的值中都不包含新行。如果不满足这些条件,所有的地狱都可能会崩溃。

使用更复杂的正则表达式,我有一个解决方案应该提取任何有效 csv 文件的第 4 列。它正确处理引用和未引用的值。引用的值可能包含逗号、转义引号和/或换行符。第 4 列输出将始终被引用,即使源不是。唯一的限制是每条记录必须至少包含 4 列。

repl "^(?:(?:[^,\q\n]*|\q(?:[^\q]|\q\q)*\q),){3}(?:\q((?:[^\q]|\q\q)*)\q|([^,\q\n]*))(?:,(?:[^,\q\n]*|\q(?:[^\q]|\q\q)*\q))*$" "\q$1$2\q" mx <input.csv >output.txt

这是一个讨厌的测试用例 csv 文件:

1,"50,
""ignore""
x","1","Warning! Q1: Value too high [W-0001]",extra," hello,""world""
more!","part A
1,2,3","I don't want this",<last column of record 1>
"2","49","1","Warning! Q1: Value too low [W-0002]",<last column of record 2>
"3","48","1","Warning! Q1: Value changing too fast.
Check for endless loop[W-0003]","<last column of record 3>"
1,2,3,"I want this part 1
and ""this"" part 2",<last column of record 4>
a,b,c,I want this unquoted value,<last column of record 5>

这是输出:

"Warning! Q1: Value too high [W-0001]"
"Warning! Q1: Value too low [W-0002]"
"Warning! Q1: Value changing too fast.
Check for endless loop[W-0003]"
"I want this part 1
and ""this"" part 2"
"I want this unquoted value"

使用批处理变量有助于记录正则表达式的逻辑,并可以轻松快速地捕获任意列集。这是使用变量的相同解决方案:

@echo off
setlocal

:: define a regex that matches a non-captured column value
set "ignore=(?:[^,\q\n]*|\q(?:[^\q]|\q\q)*\q)"

:: define a regex that matches a captured column value
:: quoted value is in $1, unquoted value is in $2
set "capture=(?:\q((?:[^\q]|\q\q)*)\q|([^,\q\n]*))"

call repl "^(?:%ignore%,){3}%capture%(?:,%ignore%)*$" "\q$1$2\q" mx <input.csv >output.txt
type output.txt

这是捕获第 1 列和第 4 列的最终 CALL 的演示

call repl "^%capture%,%ignore%,%ignore%,%capture%(?:,%ignore%)*$" "\q$1$2\q,\q$3$4\q" mx <input.csv >output.csv
于 2013-09-26T02:13:08.383 回答