2017-09-04 3 views
0

私はTCL regexpで簡略化されたCSV形式を解析しようとしています。基本的なフォーマットのコンプライアンステストを実行するために、分割して正規表現を選択しました。簡体字中国語文字列解析のためのTCLマルチキャプチャグループ

私の問題は、カウント数量を使用したいが、 '、'をマッチから除外したいということです。

私のテストライン:

set line "2017/08/21 16:06:20.0, REALTIME, late by 0.3, EOS450D, 1/640, F/8.0, ISO 100, Partial 450D 0.0%" 

は、これまでのところ私が持っている:

regexp -all {(?:([^\,]*)\,){8}} $line dummy date tm off cam exp fnum iso com 

私の思考プロセスである: 次のカンマまでコンマされていないすべての文字に一致するグループを取得します。 今私はこれを8回一致させたいので、捕捉していないグループに続けてカウント量を指定します。しかし、それは今のところ一致しないので目的を破る。私が必要とするのは、試合をCSVを8回通過させてテキストをキャプチャする方法ですが、コンマはキャプチャしません。

私のCSVは次のように簡略化されています。 CSV

でCSV 空のエントリで ません引用符で囲まれた文字列は、私は、CSVマッチングのためにグーグルをチェックしましたが、ほとんどのヒットはあまりにもよるCSVコンテンツに特殊なケースを可能に爆破されました。

おかげで、 ゲルトregexpコマンドで

+1

私は今テストすることはできませんが、コードを見ると、最後のフィールドの後にカンマがないため(適切であるため)、チョークする可能性が高いと思われます。私は、Tcllibのcsvパッケージを使ってcsvを単純化することを強くお勧めします。 –

答えて

2

は、-allスイッチと一致変数間の相互作用は、マッチングの最後の反復でキャプチャ値は変数を埋めるために使用されることです。つまり、1つのキャプチャグループを持ち、8回繰り返して8つの変数を入力することはできません。

最後のフィールドの後にコンマが必要なため、正規表現が一致しません。

この特定の例では、あなたはこれがコンマない文字のすべてのグループと一致することを意味し

% regexp -all -inline {[^,]+} $line 
{2017/08/21 16:06:20.0} { REALTIME} { late by 0.3} { EOS450D} { 1/640} { F/8.0} { ISO 100} { Partial 450D 0.0%} 

呼び出しを使用することができます(コンマは特別なものではありませんのでご注意:あなたがする必要はありませんそれをエスケープして)リストとして返します。

あなたが述べたように、これは(約5倍の速さでもある)

% split $line , 

を使用するのと同じです。あなたがやりたいことの検証の形式は不明ですが、あなたは簡単に見つかったフィールドの数を検証することができます:

あなたは、いくつかの検証をやってみたかったのでsplitを使いたくなかった

% set fields [split $line ,] 
% if {[llength $fields] ne 8} {puts stderr "wrong number of fields"} 

をあなたは、変数内のフィールドを保存し、それらを抽出しながら、同時にそれらすべてを検証しようとするよりも権利を取得するために多くの方が簡単である、それらを個別に検証することができます。

lassign $fields date tm off cam exp fnum iso com 
if {![regexp {ISO\s+\d+} $iso]} {puts stderr "in search of valid ISO"} 

最善の方法は、データを分割することはまだありますを使用している文字列パッケージ。この単純化されたCSVを今すぐ使用したいと思っても、早急に、コンマで区切られたフィールドを許可したいと思うかもしれません。

package require csv 
set fields [::csv::split $line] 

ドキュメント: csv (package)iflassignllengthpackageputsregexpsetsplitSyntax of Tcl regular expressions

ETA:先頭/末尾の空白を取り除くこと。 CSVデータは、通常、セパレータ文字で区切られた厳密に重要なテキストのフィールドに配置されるため、これは少し珍しいことです。トリムするものがある場合は、通常、データを保存するときに実行されます。

lmap field [regexp -all -inline {[^,]+} $line] {string trim $field} 

もう一つの方法は、最初のコンマの周りの空白を取り除くことであり、その後、スプリット:

split [regsub -all {\s*,\s*} $line ,] , 

良い方法はlmap/string trimフィルターを通してマッチしたグループを置くことです正規表現で分割するsplitのTcllibバリアントを使用することができます。

package require textutil 
::textutil::splitx $line {\s*,\s*} 

[^\s,][^,]*[^\s,]の以前の正規表現をスワップアウトすることもできます(2文字未満のフィールドには一致しません)。これは、あまりにも複雑になりすぎて、有用ではないように見える正規表現です。

+0

私は提案された正規表現が好きです。正規表現の一部として先行/後続のスペースをトリミングする方法はありますか? (はい、それは後で整えることができますが、それが正規表現によって返された項目に結合できる場合はいいでしょう) –

+0

@GertGottschalk:ETAでいくつかの提案をしました。 –

関連する問題