プロが教える店舗&オフィスのセキュリティ対策術

csvデータのように二重引用符が現れるデータで、\"となっていない " までを最短一致させるにはどう書けばよいでしょうか。

ab\"cd"e"fg"hi というデータから
e"fg"hi が得られるsedの命令をお教え下さい。

[^ ]でのクラス化で否定を使うようですが、うまくできません。
下のxxxの部分をお示し下さい。
$ echo ab\\\"cd\"e\"fg\"hi | sed -e 's/xxx//'

2018年7月15日

質問者からの補足コメント

  • どう思う?

    「文字列の先頭から、\"となっていない"までの最短一致部分を削除する」スクリプトを求めています。
    例を示せば「ab\"cd"e"fg"hi という文字列に作用してe"fg"hi が得られるスクリプト」です。

    No.1の回答に寄せられた補足コメントです。 補足日時:2018/07/15 08:32
  • うれしい

    一時的に置き換える _ESC_g6d3n8h7v5x7n8_ は何か意味があるものなのでしょうか?
    長い文字の羅列ならなんでもよいのでしょうか?
    なんでもよいにしても、普通の文字や制御文字などにならないように注意すればよいのでしょうか?

    No.2の回答に寄せられた補足コメントです。 補足日時:2018/07/15 08:40
  • どう思う?

    列数の異なるCSVデータが連結されているテキストデータの各行の列数を調べようとしています。
    データ区切りではなくデータ内容としての二重引用符にはその直前に\が付いています。

    Rubyは多少知っていますが、くずれたCSVを調べるモジュールがありますでしょうか?

    例えばこんな感じです。
    "ab",12,"c\"d",34,5,"e",67
    fg,8,h,i,j
    "kl",9

    No.3の回答に寄せられた補足コメントです。 補足日時:2018/07/15 08:57

A 回答 (7件)

私はそのような場合、以下のようにして処理しています。



s/\\"/_ESC_g6d3n8h7v5x7n8_/ ; s/^[^(^")]*"// ; s/_ESC_g6d3n8h7v5x7n8_"/\\"/

「\"」を一旦「_ESC_g6d3n8h7v5x7n8_」に置換し、メインの置換処理を行ってから戻しているだけです。

範囲は、「行頭」から「\"となっていない"」までです。

入力のテキストに「_ESC_g6d3n8h7v5x7n8_」が含まれる場合はうまく行きませんので、100点の方法ではないです。

もっと正攻法でスマートな方法がある気がするので、そこは私も知りたい所です。
この回答への補足あり
    • good
    • 0
この回答へのお礼

教えて頂いたsed命令で希望の処理ができました。
ありがとうございました。

お礼日時:2018/07/15 08:42

そうだね

    • good
    • 0

「sed」といってもものによって正規表現は違うのだが, 例えば


^(\\"|[^"])*"
くらいかな? もっとエスケープしないといけないかもしれんがそこはてきとうに.
    • good
    • 0

No.2です。



「_ESC_g6d3n8h7v5x7n8_」に意味は全く無いです。

入力テキストの内容の一部と重複しづらい文字列にしているだけです。

使う文字に関しましては、記述が楽な意味を持たない無難な文字を使っているだけです。

サーバーなんかの処理ですと、ユーザーから様々なデータが送られてくると思いますので、こういう文字列では駄目だと思うのですが、ローカルで事務的な作業を行う程度なら、現実的に考えてこの文字列が重複する事はなかなかありえないと思い、このような文字列を使った次第です。
    • good
    • 0
この回答へのお礼

よくわかりました。ありがとうございます。

お礼日時:2018/07/15 21:33

ちょっと確認してみました。


Rubyの場合
・CSVモジュールが利用できる
・1行が配列に変換される。
 配列の長さは「その行の項目数」と同じになる。行毎に違えば、それぞれ別になる
・\" というのは、CSV標準の方法ではないためか、対応していない

以上より、
・1行読みこむ
・\" → "" へ変換する
・CSV.parseで分割する
・列数を数える
というプログマムで目的は達成できそうです。

ーーー
https://docs.ruby-lang.org/ja/latest/class/CSV.h …
のサンプルを元に

require 'csv'
# ファイルから一行ずつ
CSV.foreach("file.csv") do |row|
p row
end

で確認したところ「Unclosed quoted field」とエラーに。

http://www.kasai.fm/wiki/rfc4180jp
> 2. CSVの書式の定義
> 7. フィールドがダブルクォーテーションで囲まれている場合、
> フィールドの値に含まれるダブルクォーテーションは、
> その直前にひとつダブルクォーテーションを付加して、
> エスケープしなければならない。

\" → "" に書き換えて再度実行
["ab", "12", "c\"d", "34", "5", "e", "67"]
["fg", "8", "h", "i", "j"]
["kl", "9"]
    • good
    • 0
この回答へのお礼

ありがとうございます。
require 'csv'
でやってみました。
列数がそろっていなくても行ごとの配列にしてくれていました。

お礼日時:2018/07/15 10:54

PerlとかPythonとかRubyとかで、CSV操作用モジュールを使う


という選択肢は無いのですか?
この回答への補足あり
    • good
    • 0

すみませんが, なにをしたいのかがわかりません. 「\"となっていない " までを最短一致させる」とあるのですが, 「どこから」\"となっていない " までを最短一致させる, というのでしょうか?



下の例, 「ab\"cd"e"fg"hi というデータからe"fg"hi が得られる」も上に書いてあるものとは食い違いがあるようにしか見えません.
この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!