challenge RFC 4180対応版 CSVレコードの分解

ある関数(splitCSV)に渡された文字列を配列に分解して列ごとに表示してください。
渡される文字列は、CSVデータの1レコードが設定されているとします。

使用するデータはK3形式が元になっている仕様で
エクセルが出力しているような形式です。

書式には次のような特徴があります。
1. 各レコードは「改行」によって区切られている。
2. 各列は「,」によって区切られている。
3. 列のデータは「"」によって囲んでも良い。
4. 列に「,」「改行」「"」いずれかを含む場合「"」で
   囲わなければならない。
5. 列データに「"」を含める場合「""」とする。

本来、改行コードはCRLFですが今回は特に指定しません。

次の入力があった場合
"aaa","b
bb","ccc",zzz,"y""Y""y",xxx

出力は
1 => aaa
2 => b
bb
3 => ccc
4 => zzz
5 => y"Y"y
6 => xxx

となります。
このお題はraynstardさんの投稿によるものです。ご投稿ありがとうございます。助かります。

Posted feedbacks - Smalltalk

Squeak Smalltalk で。

手近に CSV 解析器が見あたらなかったので、よく似た作業をする
Smalltalk 処理系の字句解析器のインスタンスをハックして
なんちゃって CSV 解析器(^_^;)を仕立ててみました。

具体的には、カンマをデリミタに、スペースを通常の文字に、
CR を閉じ括弧、LF を開く括弧に見立てるよう、スキャナのテーブルを
書き換え騙して仕事をさせます。なお、ダブルクオートは Smalltalk では
コメントアウトになってしまうので、文字列リテラルを表す
シングルクオートに差し替え、解析後、ダブルクオートに戻しています。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
| scanner typeTable data dataFile dataString |
scanner := Scanner new.
typeTable := scanner instVarNamed: #typeTable.
typeTable := scanner instVarNamed: #typeTable put: typeTable copy.
typeTable at: $, asciiValue put: #xDelimiter.
typeTable at: $  asciiValue put: #xLetter.
typeTable at: Character lf asciiValue put: #leftParenthesis.
typeTable at: Character cr asciiValue put: #rightParenthesis.
dataFile := FileStream fileNamed: 'data.txt'.
dataString := dataFile contents replaceAll: $" with: $'; copyWithFirst: $(.
data := scanner scanTokens: dataString.
World findATranscript: nil.
data do: [:record |
    record doWithIndex: [:field :index |
        field replaceAll: $' with: $".
        field := field copyWithout: Character lf.
        Transcript cr; show: ('{1} => {2}' format: {index. field})]]

Index

Feed

Other

Link

Pathtraq

loading...