以下のファイルがあります。Test.csv
"pav",12345,"ABCD,EF;xyz23;15rtg",,
"xyz",,"C4DEF;x23yu;rtg",,
修正後:
cat Test.csv
"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,
これサム""で区切られた部分文字列を含むrdフィールドは、その部分;
文字列で置き換える必要があります。
答え1
以下が使用されますcsvkit
参照フィールドにカンマを含むCSVデータを直接解析すると、awk
エラーが発生しやすいためです。
これにより、正しい形式の3番目の列が生成されます。
csvcut -c 3 file.csv |
sed -r 's/^"|"$//g' |
awk -F';' -vOFS=';' '{ for (i=1; i<=NF; ++i) $i = substr($i, 0, 2) } { printf("\"%s\"\n", $0) }' >tmp-3rd
与えられた入力に対して、これは以下を生成します。
"AB;xy;15"
"C4;x2;rt"
csvcut
3番目の列が切り捨てられます。sed
すべての二重引用符が行の最初または最後に表示されると、データから削除されます。- プログラムは、区切りフィールドを
awk
繰り返してフィールド;
ごとに2文字の長さに短縮します。二重引用符でデータを印刷します。 - 出力はファイルに書き込まれます
tmp-3rd
。
次に、元のデータに再組み立てします(これは、手続き型置換をbash
実行するために使用できる別のシェルであると仮定します<(...)
)。
paste -d, <( csvcut -c 1,2 file.csv ) tmp-3rd <( csvcut -c 4,5 file.csv ) | csvformat
paste
列はカンマで区切られ、一緒にグループ化されます。- 最初のプロセスは元のファイルの最初の2つの列を置き換え、2番目のプロセスは最後の2つの列を置き換えます。中央には、修正された3番目の列があります。
csvformat
オプションのステップとして、必要に応じてフィールドを参照または逆参照してデータを渡します。
出力は次のとおりです
pav,12345,AB;xy;15,,
xyz,,C4;x2;rt,,
一時ファイルの必要性をバイパスします。
paste -d, \
<( csvcut -c 1,2 file.csv ) \
<( csvcut -c 3 file.csv | sed -r 's/^"|"$//g' |
awk -F';' -vOFS=';' '{ for (i=1; i<=NF; ++i) $i = substr($i, 0, 2) } { printf("\"%s\"\n", $0) }' ) \
<( csvcut -c 4,5 file.csv ) | csvformat
答え2
そしてperl
;
3番目のフィールドでのみ仮定
$ perl -pe 's/"\K[^;"]*;[^"]*(?=")/$&=~s|([^;]{2})[^;]+|$1|gr/e' ip.txt
"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,
"\K
"
関心文字列の前と関心文字列の後に一致します(?=")
。"
ただし、"
これは予測文字列なので、キャプチャ文字列自体の一部ではありません。[^;"]*;[^"]*
;
-OR以外の"
文字の後に非;
文字"
が続くものと一致します。$&=~s|([^;]{2})[^;]+|$1|gr
一致する文字列に対して別の置換を実行します。e
Modifierを使用すると、交換部品にPerlコードを使用できます。
3番目のフィールドのみを制限
$ cat ip.txt
"pav",12345,"ABCD,EF;xyz23;15rtg",,
"xyz",,"C4DEF;x23yu;rtg",,
"foo;12,23;good",124,253
12,5232,"xyz","ijk;5545;62"
$ perl -pe 's/^("[^"]*",|[^,]*,){2}"\K[^;"]*;[^"]*(?=")/$&=~s|([^;]{2})[^;]+|$1|gr/e' ip.txt
"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,
"foo;12,23;good",124,253
12,5232,"xyz","ijk;5545;62"
答え3
正確で堅牢Python3.xソリューション(ベースcsv.reader目的):
parse_csv.py
スクリプト:
import csv, sys
with open(sys.argv[1]) as f:
reader = csv.reader(f)
for l in reader:
l = [s if ';' not in s else ';'.join(_[:2] for _ in s.split(';')) for s in l]
print(','.join(i if not i or i.isnumeric() else '"{}"'.format(i) for i in l))
使用法:
python3 parse_csv.py Test.csv
出力:
"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,
Pythonのモジュールは、csv
データの強力で柔軟なサポートを提供します。csv
答え4
複雑なGNUAWK
ソリューション(csv
データ解析):
awk -v FPAT='"[^"]+"|[^",]+|,,' '{
for (i=1;i<=NF;i++) {
if ($i~/^".*;./) {
len=split($i,a,";"); v=substr(a[1],1,3);
for (j=2;j<=len;j++) v= v";"substr(a[j],1,2);
v=v"\042"
} printf "%s%s",(v? v: ($i~/^,,/? (i==NF? ",":""):$i )),
(i==NF? ORS:OFS); v=""
}
}' OFS=',' Test.csv
FPAT='"[^"]+"|[^",]+|,,'
- フィールド値の複雑な正規表現パターンの定義if ($i~/^".*;./) ...
- 現在のフィールドに文字が$i
含まれている場合;
len=split($i,a,";")
- フィールド値を$i
区切り記号として配列に分割します。生成された要素/ブロックの数が割り当てられます。a
;
len
v=substr(a[1],1,3);
- 先頭文字を含む必要な長さの最初のブロックをキャプチャします"
。"AB
から抽出されます"ABCD,EF
for (j=2;j<=len;j++) ...
- 残りのチャンク/アイテムを繰り返します。v=v"\042"
-"
処理されたシーケンスに末尾の二重引用符を追加しますv
。\043
二重引用符で囲まれたcharを表すASCII 8進コード"
。($i~/^,,/? (i==NF? ",":""):$i )
- 各空のフィールドは、単一のカンマと共通の区切り文字を使用して,,
再生成されます。これは不要なコンマの混乱を避けるためです。,
,
"pav",,,
(i==NF? ORS:OFS)
- 最後のフィールドが見つかった場合i==NF
- レコード区切り文字を印刷しORS
、それ以外の場合 - フィールド区切り文字を印刷します。OFS
出力:
"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,