- PR -

正規表現でダブルクォーテーション囲み&カンマ区切りを表現したい

1
投稿者投稿内容
EOSB200
会議室デビュー日: 2004/04/01
投稿数: 18
投稿日時: 2004-07-12 01:18
こんにちは。
VB.NETでプログラミングしています。
自作クラスのプロパティ値(string)に複数の値(複数の文字列)をセットしたく、正規表現でダブルクォーテーション囲み&カンマ区切りを表現したいのですが、なかなか上手くいきません。
(プロパティ値をどうしても1つの文字列として扱いたく、複数の文字列のシリアル化を考えたのですが、バイナリ等になるとメンテナンスが大変になるので、正規表現に走りました。)

[正規表現で表したいこと]
・1つの文字列はダブルクォーテーションで囲む
・複数個の文字列はカンマで区切る(カンマで終了してはいけない)
・ヌル、スペース、タブは文字列として許さない
・正規表現をクリアした場合は、ダブルクォーテーションを含まない文字列をキャプチャしたい

例.

OK:
"abc" → abcをキャプチャ
"abc","def","ghi" → abcとdefとghiをキャプチャ
"ab"c","d,ef" → ab"cとd,efをキャプチャ

NG:
"abc",
""
" "
"","abc"


勉強不足で恐縮ですが、ご教授の程よろしくお願い致します。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-07-12 08:51
 私も色々考えたのですが...外部からは与えられない、と考えていいのでしょうか?外部から、「abc,"aa""bb""cc",cde」(abc aa"bb"cc cde)と与えられたら、どうなるのでしょう?
 そういうことを考えると、「"""csv"",""in"",""csv"""」なんてことをやられると、とっても面倒なんですよね

 先読みか、後戻りが必要なので、正規表現でするのは、ちょっと苦しいかと。。。

[ メッセージ編集済み 編集者: Jitta 編集日時 2004-07-12 08:51 ]

項目数が決まっているなら、
^".+",(".+",){項目数-2}".+"$
で、検査はできると思います。取り出しは、CaptureCollectionクラスかなぁ?

[ メッセージ編集済み 編集者: Jitta 編集日時 2004-07-12 12:13 ]
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-07-12 12:16
ども、ほむらです。

いわゆるエクセルで出力するようなK3形式のCVSを分解できればよいのですよね?
以前にもどこかで出した記憶があるのですがperlだとできるのでJavaや.NETみたいな
正規表現を持っているものであればできると思いますよ。
最悪個人ユースであればpcre.dllを利用してみるとか

ポイントは最短マッチと最長マッチの組み合わせです。
"が続かない最長マッチ
または"を含まない,までの最短マッチ

# とりあえず列の取り出し;
my @result = ($work =~ m/((?:\".*?[^\"]\")[ \t]*|(?:.*?))\,/sg);
# /sgは .に改行を含めてGlobal検索を有効にするということです。
# /s がない場合には(?:.|\r\n)で代用できるはず。
# @result は列を保存するための一元配列です

くわしくはこちらをどうぞ。
http://www.google.co.jp/search?q=site%3Awww.atmarkit.co.jp+%E3%81%BB%E3%82%80%E3%82%89%E3%81%A7%E3%81%99%E3%80%82+perl+CSV&ie=UTF-8&hl=ja&btnG=Google+%E6%A4%9C%E7%B4%A2&lr=lang_ja
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-07-12 15:36
ども、ほむらです。

.NETのところで何度もPerlの話をするのも気が引けたので
勉強がてらVB.NETで作ってみました。
初めてのプログラムなので変な記述になっている部分が多いかと思います。

分解してArrayListに追加する部分でデータの整合性チェックなどをしているのですが
この部分でバグがあるらしく、""というデータでエラーになってくれません。
あくまで参考程度にどぞ。

追伸:
変なところとか、改善点はどんどん指摘してもらえるとうれしいです。

#BBコード記述ミスを修正

コード:

Makefile
---------
LIBSOPT=/r:System.dll /r:Mscorlib.dll
OPT=/optimize+ /debug- /nologo /optionexplicit+ /optionstrict+

ALL: csvtest.vb
vbc.exe $(OPT) $(LIBSOPT) csvtest.vb

---------
csvtest.vb
---------------
Option Strict On
Option Explicit On

Imports System
Imports System.Text.RegularExpressions
Imports System.Collections

Class Application
Public Shared Sub Main( argv() as String )
Dim DATA As String = "abc,,""rr""""r""""r"",ty,"""",yyu,"""""",lll"
Dim rePATTERN As String = "^(((?:"".*?[^""]"")[ \t]*|(?:.*?)),)+"

Dim rows as ArrayList
rows = RecordSplit(DATA, rePATTERN)
Display(rows)
End Sub

' すべての列データを表示
Public Shared Sub Display(Rows as ArrayList)
Dim wkRI as Integer
For wkRI = 0 To Rows.Count -1
Console.Writeline(wkRI & ":" & Rows(wkRI).ToString())
Next wkRI
End Sub

' 1件のレコードを列に分解してArrayListに格納する
Public Shared Function RecordSplit(DATA as String, rePATTERN as String) As ArrayList
Dim m as Match
Dim cc as CaptureCollection
Dim matches as MatchCollection
Dim result as New ArrayList()

' 正規表現にマッチさせるために最後,を追加
matches = Regex.Matches( DATA & ",", rePATTERN, RegexOptions.Singleline)
IF matches.Count = 0 Then
Console.WriteLine("マッチしませんでした")
return result
End if

Dim wkGI as Integer = 0
Dim wkCI as Integer = 0
Dim szMatch As String

m = matches.item(0)
wkGI = m.Groups.Count -1
While m.Groups( wkGI ).Value <> ""
cc = m.Groups(wkGI).Captures
For wkCI=0 To cc.Count - 1
' マッチしたデータの修正
szMatch = cc(wkCI).ToString()
if szMatch = "" then
Console.WriteLine("DATA Error(" & wkCI & "):" & """" & szMatch &"""")
end if
If szMatch.indexOf("""") <> -1 then
' クォーテーション削除
szMatch = szMatch.Substring(1,szMatch.length - 2 )
' 二重引用符を一つに
szMatch = szMatch.Replace("""""","""")
end if
result.Add( szMatch )
Next wkCI
wkGI = wkGI + 1
End While
return result
End Function
End Class



[ メッセージ編集済み 編集者: ほむら 編集日時 2004-07-12 15:38 ]
EOSB200
会議室デビュー日: 2004/04/01
投稿数: 18
投稿日時: 2004-07-12 15:53
Jittaさん、ほむらさん、ご返答ありがとうございます。
早急にご返答頂いたのですが、なにせ正規表現(VB.NETも)初心者なもので、ご返答頂いた内容を理解して自分のものにするのに少々時間がかかりそうです。(なさけない・・・)
まずはお礼まで。
1

スキルアップ/キャリアアップ(JOB@IT)