CSVフォーマッター
カスタム区切り文字オプションを使って CSV データを整形・正規化
CSV 入力
整形済み CSV
CSV 整形とは?
CSV(Comma-Separated Values)整形とは、生のタブラーテキストを正規化するプロセスです。区切り文字、クォート、空白、改行コードが一貫したルールに従うようにデータを書き直します。2005年に公開された RFC 4180 は最も広く採用された CSV 標準を定義しています。フィールドはカンマで区切り、レコードは CRLF で終端し、カンマ・ダブルクォート・改行を含むフィールドはダブルクォートで囲むという規則です。CSV フォーマッターは、乱雑または不整合な CSV データをこれらの規則に合わせて書き直します。
実際の CSV ファイルがクリーンな状態で届くことはほとんどありません。Excel、Google Sheets、データベースのダンプユーティリティから出力されるスプレッドシートは、それぞれ異なるクォート戦略を採用し、空白の扱いも異なり、カンマの代わりにセミコロンやタブを使用する場合があります。これらのファイルを RFC 4180 準拠の入力を期待するパーサーに渡すと、行の崩れ、列のずれ、またはデータの消失が発生することがよくあります。処理前に整形しておくことで、こうした問題を早期に発見できます。
CSV フォーマッターと CSV コンバーターは異なります。整形はデータを CSV のまま保持します。クォートを正規化し、余分な空白をトリムし、列を揃え、必要に応じて区切り文字を変更します。変換はフォーマットそのものを変え、JSON、HTML、SQL、Markdown などの形式に出力します。
この CSV フォーマッターを使う理由
このツールは CSV の解析と再シリアライズをすべてブラウザ内で行います。データがマシンの外に出ることはありません。
CSV フォーマッターの使用例
CSV のクォートとエスケープルール(RFC 4180)
RFC 4180 は、フィールドをいつ、どのようにクォートするかについて具体的なルールを定義しています。以下の 6 つのシナリオは、クォートの動作が重要になるケースを網羅しています。
| シナリオ | 例 | ルール |
|---|---|---|
| Field contains delimiter | name,"Smith, Jr." | Wrap in double quotes |
| Field contains newline | "line1\nline2" | Wrap in double quotes |
| Field contains double quote | "She said ""hello""" | Double the quote character |
| Field is empty | ,, | Two consecutive delimiters |
| Field has leading spaces | " value" | Quotes preserve whitespace |
| Field is numeric | 42 | No quotes required unless forced |
CSV 区切り文字の比較
区切り文字の選択は、互換性、可読性、クォートが必要なフィールドの頻度に影響します。
コード例
以下の例は、乱雑な CSV を解析し、異なるプログラミング言語で一貫したフォーマットに再シリアライズする方法を示しています。各コードは空白のトリム、区切り文字の正規化、クォートを処理します。
import { parse, unparse } from 'papaparse'
const messy = `name, age ,city
Alice , 30, Berlin
Bob,25 , " Tokyo "`
// Parse with trimming, then re-serialize with consistent formatting
const parsed = parse(messy, {
header: true,
skipEmptyLines: true,
transformHeader: h => h.trim(),
transform: v => v.trim(),
})
const clean = unparse(parsed.data, { quotes: true })
console.log(clean)
// → "name","age","city"
// → "Alice","30","Berlin"
// → "Bob","25","Tokyo"import csv
import io
messy = """name, age ,city
Alice , 30, Berlin
Bob,25 , " Tokyo " """
reader = csv.DictReader(io.StringIO(messy), skipinitialspace=True)
output = io.StringIO()
writer = csv.DictWriter(
output,
fieldnames=[f.strip() for f in reader.fieldnames],
quoting=csv.QUOTE_ALL,
)
writer.writeheader()
for row in reader:
writer.writerow({k.strip(): v.strip() for k, v in row.items()})
print(output.getvalue())
# → "name","age","city"
# → "Alice","30","Berlin"
# → "Bob","25","Tokyo"package main
import (
"encoding/csv"
"fmt"
"strings"
)
func main() {
input := "name,age,city\nAlice,30,Berlin\nBob,25,Tokyo"
r := csv.NewReader(strings.NewReader(input))
records, _ := r.ReadAll()
var buf strings.Builder
w := csv.NewWriter(&buf)
w.UseCRLF = true // RFC 4180 line endings
for _, record := range records {
_ = w.Write(record)
}
w.Flush()
fmt.Print(buf.String())
// → name,age,city\r\n
// → Alice,30,Berlin\r\n
// → Bob,25,Tokyo\r\n
}# Re-format a CSV file with csvkit (Python-based) csvformat -D ";" input.csv > output.csv # Convert tabs to commas csvformat -t input.tsv > output.csv # Force-quote all fields csvformat -U 1 input.csv > quoted.csv # Using Miller (mlr) to normalize mlr --icsv --ocsv --quote-all cat input.csv > clean.csv