正規表現は素晴らしいものです :) 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