1

Windows バッチ ファイルの文字列の引用符に問題があります。csv ファイル (区切り) と複数行のエントリを解析しようとしています。4 番目の sperator の後の文字列のみをテキスト ファイルとして書き出す必要があります。結果には、新しい行と引用符が含まれている必要があります。

入力:

"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

1

正規表現は素晴らしいものです :) REPL.BAT と呼ばれるハイブリッド JScript/バッチ ユーティリティを使用できます。これは、標準入力で正規表現の検索と置換を実行し、結果を標準出力に書き込みます。

REPL.BAT が現在のディレクトリ、またはさらに良いことに、パス内のどこかにあると仮定すると、次の 1 つのライナーがコマンド ラインから直接機能します。

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

上記のソリューションでは、すべてのレコードに少なくとも 4 つの列 (3 つのコンマ) が含まれていることを前提としています。また、最初の 3 列には値にコンマが含まれていないこと、4 番目の列は引用符で囲まれている必要があり、エスケープされた quote が含まれていてはならないこと""、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 に答える