RFC 4180対応版 CSVレコードの分解
Posted feedbacks - Other
PEG (Parsing expression grammar) ベースのパターンマッチ OOPL である OMeta で。
OMeta には、COLA(Combined Object-Lambda Architecture; aka, Pepsi&Coke)、Squeak Smalltalk、JavaScript での実装がありますが、ここでは Squeak OMeta を用い、Doukaku33 として定義しました。
実行例
| in record |
in := '"aaa","b
bb","ccc",zzz,"y""Y""y",xxx'.
record := (Doukaku33 onTree: nil) apply: #レコード withArguments: in.
World findATranscript: nil.
record doWithIndex: [:field :idx | Transcript cr; show: idx; show: ' => ', field]
出力
1 => aaa
2 => b
bb
3 => ccc
4 => zzz
5 => y"Y"y
6 => xxx
OMeta には、COLA(Combined Object-Lambda Architecture; aka, Pepsi&Coke)、Squeak Smalltalk、JavaScript での実装がありますが、ここでは Squeak OMeta を用い、Doukaku33 として定義しました。
実行例
| in record |
in := '"aaa","b
bb","ccc",zzz,"y""Y""y",xxx'.
record := (Doukaku33 onTree: nil) apply: #レコード withArguments: in.
World findATranscript: nil.
record doWithIndex: [:field :idx | Transcript cr; show: idx; show: ' => ', field]
出力
1 => aaa
2 => b
bb
3 => ccc
4 => zzz
5 => y"Y"y
6 => xxx
see: OMeta: an Object-Oriented Language for Pattern Matching
1 2 3 4 5 | レコード ::= <列>:first ($, <列>)*:rest => [rest addFirst: first; yourself]
列 ::= (<クオートあり> | <クオートなし>):xs => [String withAll: xs]
クオートあり ::= $" ($" $" => [$"] | ~$" <char>)+:xs $" => [xs]
クオートなし ::= (~(<改行> | $, | $") <char>)*
改行 ::= <exactly (Character cr)>
|
VBScriptはテキスト加工に適した言語なのですが、 まだ投稿がなかったのでやってみました。 C#版の単純移植なので、あまり綺麗なコードではありません。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | s = """aaa"",""b" & vbCrLf & "bb"",""ccc"",zzz,""y""""Y""""y"",xxx"
ss = splitCSV(s)
i = 1
For Each elem In ss
WScript.Echo i & " => " & elem
i = i + 1
Next
Function splitCSV(s)
If IsNull(s) Then
splitCSV = Null
Exit Function
End If
Dim a()
index = 0
result = ""
i = 1
While i <= Len(s)
b = (mid(s, i, 1) = """")
If b Then
i = i + 1
End If
If b Then
j = InStr(i, s, """")
Else
j = InStr(i, s, ",")
End If
If j < 1 Then
j = Len(s) + 1
End If
t = mid(s, i, j - i)
If b And (j < Len(s) - 1) And Mid(s, j+1, 1) = """" Then
result = result & t
result = result & """"
i = j + 1
Else
ReDim Preserve a(index)
a(index) = result & t
index = index + 1
result = ""
If b Then
i = j + 2
Else
i = j + 1
End If
End If
Wend
splitCSV = a
End Function
|


raynstard
#3389()
Rating1/1=1.00
[ reply ]