1つ以上の中括弧セットの外側にある複数のカンマを置き換え、1つ以上の中括弧セット内の例外を置き換えます。

1つ以上の中括弧セットの外側にある複数のカンマを置き換え、1つ以上の中括弧セット内の例外を置き換えます。

テキストファイルに複数のレコードがあります。各レコードにはカンマで区切られた複数の列があり、一部の列には中括弧セットが1つ、他の列に複数の中括弧があります。

以下を行う必要があります。

  1. 1つ以上の中括弧セットの外側にコンマがある場合は、コンマを垂直バーに置き換える必要があります。

  2. 1つ以上の中括弧セット内にカンマがある場合は、そのカンマを保持する必要があります。THING1,{THING2,{THING3,}},THING4したがって、与えられた出力はTHING1|{THING2,{THING3,}}|THING4

レコードサンプル:

(999969,2500,"777777888",0,"45265","65522",NULL,10001,2014-09-15 10:27:07.287,2014-09-15 10:28:49.085,2014-09-15 06:28:50.000,0,0,NULL,"text","401c4133091977",{F,F,"711592473,"00967711580001,F,NULL,NULL,"421010617759466","'401c4133091977H'",NULL,NULL,NULL,NULL,NULL,NULL,1,1,10,1,0,0,0,"a30200000000276f",NULL},NULL,{gggg{-1, 0, -1, 1410762530000, 87, 0, 0}, rrrr[{"foot", 24000, 976000, 3999-12-31 23:59:59, 0}], rrrr[{1000003, 1410762443000, 120, 87, 0, 0, 2, 1, 24000, 0, 0}]},{dd=0, ff=0, gg=0, hh=1, ctr="live", dddd="52265", eni=55, cuc=1},NULL,NULL,NULL,NULL,NULL,{NULL,NULL,NULL,0,"wwww","eeee",2014-10-10 10:45:59.000,2015-03-09 23:59:59.000,2015-06-07 23:59:59.000,2015-08-06 23:59:59.000,NULL})

結果は次のとおりです。

(**999969|2500|"777777888"|0|"45265"|"65522"|NULL|10001|2014-09-15 10:27:07.287|2014-09-15 10:28:49.085|2014-09-15 06:28:50.000|0|0|NULL|"text"|"401c4133091977"|**{F,F,"711592473,"00967711580001,F,NULL,NULL,"421010617759466","'401c4133091977H'",NULL,NULL,NULL,NULL,NULL,NULL,1,1,10,1,0,0,0,"a30200000000276f",NULL}**|NULL|**{gggg{-1, 0, -1, 1410762530000, 87, 0, 0}, rrrr[{"foot", 24000, 976000, 3999-12-31 23:59:59, 0}], rrrr[{1000003, 1410762443000, 120, 87, 0, 0, 2, 1, 24000, 0, 0}]}**|**{dd=0, ff=0, gg=0, hh=1, ctr="live", dddd="52265", eni=55, cuc=1}**|NULL|NULL|NULL|NULL|NULL|**{NULL,NULL,NULL,0,"wwww","eeee",2014-10-10 10:45:59.000,2015-03-09 23:59:59.000,2015-06-07 23:59:59.000,2015-08-06 23:59:59.000,NULL})

ベストアンサー1

Perl+組み合わせで簡単にregexできます。

perl -pe 's/(\{(?:[^{}]|(?1))*\})(*SKIP)(*F)|,/|/g' file

例:

$ perl -pe 's/(\{(?:[^{}]|(?1))*\})(*SKIP)(*F)|,/|/g' file
(999969|2500|"777777888"|0|"45265"|"65522"|NULL|10001|2014-09-15 10:27:07.287|2014-09-15 10:28:49.085|2014-09-15 06:28:50.000|0|0|NULL|"text"|"401c4133091977"|{F,F,"711592473,"00967711580001,F,NULL,NULL,"421010617759466","'401c4133091977H'",NULL,NULL,NULL,NULL,NULL,NULL,1,1,10,1,0,0,0,"a30200000000276f",NULL}|NULL|{gggg{-1, 0, -1, 1410762530000, 87, 0, 0}, rrrr[{"foot", 24000, 976000, 3999-12-31 23:59:59, 0}], rrrr[{1000003, 1410762443000, 120, 87, 0, 0, 2, 1, 24000, 0, 0}]}|{dd=0, ff=0, gg=0, hh=1, ctr="live", dddd="52265", eni=55, cuc=1}|NULL|NULL|NULL|NULL|NULL|{NULL,NULL,NULL,0,"wwww","eeee",2014-10-10 10:45:59.000,2015-03-09 23:59:59.000,2015-06-07 23:59:59.000,2015-08-06 23:59:59.000,NULL})

説明する:

正規表現を2つの部分に分けて説明します。

  1. (\{(?:[^{}]|(?1))*\})
  2. (*SKIP)(*F)|,

パート1

(\{(?:[^{}]|(?1))*\})
  • このトリックは、中かっこが正しくペアになっている場合にのみ機能します。
  • ()キャラクタをキャプチャするために使用されるキャプチャグループです。
  • \{開く中かっこに一致します。
  • (?:[^{}]|(?1))

    • (?:...)非キャプチャグループと呼ばれます。
    • [^{}]すべての文字に一致するが一致し{ない}
    • |論理OR演算子。
    • (?1)最初のキャプチャグループに再帰します。
  • (?:[^{}]|(?1))*以前のトークンと0回以上一致します。
  • \}終了}記号。

次の例とその中に入れ子にされた括弧に一致するパターンを考えてみましょう。

ひも:

h{foo{bar}foobar}

パターン:

h(\{(?:[^{}]|(?1))*\})
  • まず、正規表現エンジンは次のように一致しようとしますhこのパターンにあります。) 入力文字列の場合。したがって、最初の文字がh一致します。
  • バランスカッコを探すパターンは、キャプチャグループに入力されます。
  • エンジンは\{パターンの2番目の文字(たとえば)を取得し、入力文字列と比較しようとします。だから最初の人{が得た。キャプチャされます\{キャプチャグループ内にあるため、「一致」ではなく「キャプチャ」という単語を使用してください。
  • (?:[^{}]|(?1))*これは、正規表現エンジンがゼロ回以上の文字を{除くすべての文字と一致するように指示します。または、文字}が見つかった場合は、最初のキャプチャグループに戻ります。これで文字列がキャプチャされました。次の文字があるため、最初のキャプチャグループに再帰されます。これで、正規表現エンジンの再帰レベルが1段階低下しました。最初のキャプチャグループの最初のパターンは何ですか({}foo{正規表現を見る)?はい\{、これは{文字列の後ろの記号と一致しますfoo
  • エンジンの再帰深度はまだ1レベルで、パターンは(?:[^{}]|(?1))*文字列と再一致しますbar。今後barの文字は、}文字列を一致させた後にbar正規表現エンジンが介入しないため、非(?1)キャプチャグループを繰り返す理由です。若いまたはそれ以上。次のモード(以降のモデル(?:[^{}]|(?1))*)は正規表現からです\}。したがって、これは直後の中括弧\}と一致します。正規表現エンジンは1つのレベルの再帰から外れ、パターンは次の文字列と一致します。最後は最後の支柱と一致します。}bar[^{}]*foobar\}
  • 今最初のキャプチャグループに{foo{bar}foobar}

第二部

  • (*SKIP)(*F)一致またはキャプチャ失敗を引き起こす文字です。したがって、この例では、キャプチャされたすべてのバランス括弧をスキップします。つまり、正規表現エンジンが文字列の残りの文字と一致するように強制します。
  • 構文または形式(*SKIP)(*F)

        part1(*SKIP)(*F)|part2
         |                  |
     |----                  -----> Match this
    Don't match this 
    
  • したがって、それに続くパターンは|残りの文字列(入れ子にされた中かっこを除く文字列)。

  • 私たちの場合、次のパターン|はです,。したがって、入れ子になった中括弧の外側のすべてのコンマが一致します。

読むこれ理解するRegular Expression Recursion

メモ:

  • (?R)完全なサブパターン、つまり完全一致を繰り返します。私たちも(?R)使えます。(?0)
  • (?1)最初のサブパターンを繰り返します(つまり、最初のキャプチャグループ内のパターン)。

おすすめ記事