質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

2回答

3767閲覧

正規表現でダブルクォーテーションで括られた文字列内のダブルクォーテーションの検索方法

k2xx

総合スコア1

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2022/03/04 05:50

正規表現を用いて、CSVデータ内に括り文字以外のダブルクォーテーションを検索したいのですが
どのように表現すれば良いかご掲示頂けないでしょうか。
(言語はC#での開発を予定していますが、まずは秀丸エディタなどのテキストエディタで検索できれば。と考えております)

例)以下のようなCSVデータの場合2行目を検索したい
123, "abc", "123abc"
456, "def", "456"def" ←検索対象
789, "ghi", "789,ghi"

また、上記が可能な場合、さらに発展してエスケープされているダブルクォーテーションを除外する
正規表現の指定は可能でしょうか?

例)以下の2行目は検索対象となるが、3行目は対象外となる
123, "abc", ""
456, "def", "456"d"ef" ←検索対象
789, "ghi", "78""9""ghi" ←検索対象外

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nukasa

2022/03/04 06:48

CSVとして、ダブルクォーテーションがエスケープされた状態と、エスケープされていない状態が混在するのはおかしいです。ダブルクォーテーションをエスケープしないという仕様であれば、カラムの途中にダブルクォーテーションが出てきたら、そこでカラムの終端と解釈する、すなわち、ダブルクォーテーションはカラムの内部に出現してはならないというのがルールです。 もし、当該CSVの仕様として、ダブルクォーテーションはエスケープするとなっているのであれば、 456, "def", "456"d"ef" ←検索対象 は、パーズエラーにならなければおかしいです。
guest

回答2

0

以下で使用している正規表現ライブラリは PCRE(Perl Compatible Regular Expressions)です。また、直接的な正規表現ではなく、スタンダードな CSV 行に適合する正規表現にはマッチしない行を抽出しています。

bash

1$ grep --version 2grep (GNU grep) 3.7 3$ grep --help | grep -E -- '(-P|-v),' 4 -P, --perl-regexp PATTERNS are Perl regular expressions 5 -v, --invert-match select non-matching lines 6 7$ grep -Pv '^(?:(?:[^",]*+|"(?:[^"]*+|"")*"),\s*)*(?:(?:[^",]*+|"(?:[^"]*+|"")*"))$' <<'EOD' 8123, "abc", "123abc" 9456, "def", "456"def" 10789, "ghi", "789,ghi" 11EOD 12456, "def", "456"def" 13 14$ grep -Pv '^(?:(?:[^",]*+|"(?:[^"]*+|"")*"),\s*)*(?:(?:[^",]*+|"(?:[^"]*+|"")*"))$' <<'EOD' 15123, "abc", "" 16456, "def", "456"d"ef" 17789, "ghi", "78""9""ghi" 18EOD 19456, "def", "456"d"ef"

また、上記が可能な場合、さらに発展してエスケープされているダブルクォーテーションを除外する正規表現の指定は可能でしょうか?

正規表現に \G(match previous matching point) が使えるのであれば可能かもしれません。

投稿2022/03/05 00:19

編集2022/03/05 00:20
melian

総合スコア19803

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k2xx

2022/03/06 14:44

melian様 コメント有難う御座います。 1件目のコメントで頂戴しておりましたotn様への返答コメントでも記載しておりますが CSVとして正しい形式か否かをチェックする術を探していた為、ご提示頂いた正規表現の内容で、要件を完全な形で満たすことが出来そうです。 ※本サイトの趣旨的には、こちらの質問の内容に対する技術的なアプローチとして、otn様の正規表現内容がより質問への直接的な回答のように感じられた為、大変恐縮ながらベストアンサーはotn様のコメントとさせて頂きましたが、お二方に頂戴したそれぞれを実装に落とし込んで見たいと思います。
guest

0

ベストアンサー

正しいCSV形式か、不正なCSV形式かの判断だけであれば正規表現で出来ますが、
不正の原因である"の特定や削除はプログラムのロジックでないと無理だと思います。CSVのパーサーを書くみたいな。

追記

「前に奇数個の"があり、後ろに" , 末尾 が続かない"」という条件だと出来ますね。

Ruby

1data = [ 2'123, "abc", "123abc"', 3'456, "def", "456"def", "aaaa"xxxx"', 4'789, "ghi", "aaa,""xxxx", "789,ghi"' 5] 6 7data.each do |s| 8 p s.gsub(/^[^"]*"[^"]*(?:"[^"]*"[^"]*)*?\K"(?!\s*(?:[",]|$))/,"") 9end

この条件だけで目的にかなうのかは不明。
1行に複数個の不正"があっても1つ目しか置換されないので、置換が発生した場合は再度実行する必要があります。

投稿2022/03/04 13:16

編集2022/03/04 23:07
otn

総合スコア84557

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k2xx

2022/03/04 14:19

コメントありがとうございます。 やはり難しいですかね。。 各所で事例を検索して見つからなかったので、正規表現での検出は難しいかも。と半ば諦めつつ、最後の拠り所としてこちらに質問を投稿させて頂いた次第です。 他に妙案的なコメントを頂けることを僅かながらに期待しつつ、数日程コメントが付かない場合は、本質問はクローズさせて頂きたいと思います。 なお、TextFieldParserやCsvHelperなどのライブラリを用いることで、読み込んだ各データ行ごとにエスケープされていないダブルクォーテーションのようなCSV規約違反となる行が存在した場合、ライブラリの仕様としてエラーとしてハンドリングしてくれることは確認済みなので、正規表現での対応が難しい場合は当該手段でバリデータの処理を実装する予定で検討しております。
otn

2022/03/04 22:40

ちょっと考えてみます。
k2xx

2022/03/06 14:32

otn様 再度コメント頂き有難う御座います。 担当顧客が使用しているシステムにおいて、CSVデータを取り込む機能があるのですが、バリデータの処理が甘く、できるだけコストをかけない簡易的な方法で事前チェックする外的手段を検討していたのですが、ご提示頂いた正規表現の内容でほぼ要件を満たせそうです。 現状は未だ、正規表現の動作を確認する各種サイト様での検証しかしておりませんが、手元の環境で動作できる内容に落とし込むことを検討してみます。 この度は貴重なお知恵を頂き有難う御座いました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問