コマンドラインから(入れ子になった)テキスト引用符を削除する

コマンドラインから(入れ子になった)テキスト引用符を削除する

コマンドラインで大量のテキストを解析し、すべての(ネストされた)テキスト引用符を空白に置き換える必要があります。引用符は特定の構文で表示されます[quote=username]quoted text[/quote]

入れ子になった引用符を含む入力の例は次のとおりです。

text part 1 [quote=foo] outer quote 1 [quote=bar] inner quote [/quote] outer quote 2 [/quote] text part 2 [quote=foo-bar] next quote [/quote] text part 3

予想される出力は次のとおりです。

text part 1   text part 2   text part 3

の助けを借りてこの問題どういうわけか動作させましたが(上記の出力を得ました)、sed ':b; s/\[quote=[^]]*\][^[\/]*\[\/quote\]/ /g; t b'中間部分( ]には引用符または同じ文字を[^[\/]含めることができるため問題があります。[]

つまり、sed入力がたとえば次のような場合、私のコマンドは機能しません。

text part 1 [quote=foo] outer quote 1 [quote=bar] inner quote [foo] [/quote] outer quote 2 [/quote] text part 2 [quote=foo-bar] next quote [/quote] text part 3

1つの問題は、sed貪欲な修飾子をサポートしていないようで、可能な限り長い一致が常に入力からキャプチャされることです。扱いにくいㅏ)ユーザー名と雨)一般的な引用。

私はこれがsedこの問題のための最善のツールではなく、そのようなことをすることができないかもしれないと思います。たとえば、おそらく。perlそれともawkもっとうまくいくでしょうか?

今最後の質問は、この問題を解決するための最良かつ効率的な方法は何ですか?

ベストアンサー1

入力に文字が含まれていないことがわかっている場合は、次のことができます<>

sed '
  # replace opening quote with <
  s|\[quote=[^]]*\]|<|g
  # and closing quotes with >
  s|\[/quote\]|>|g
  :1
    # work our way from the inner quotes
    s|<[^<>]*>||g
  t1'

<または、文字を含めることができる場合は、>次のスキームを使用してエスケープできます。

sed '
  # escape < and > (and the escaping character _ itself)
  s/_/_u/g; s/</_l/g; s/>/_r/g

  <code-above>

  # undo escaping after the work has been done
  s/_r/>/g; s/_l/</g; s/_u/_/g'

AND perl、再帰正規表現の使用:

perl -pe 's@(\[quote=[^\]]*\](?:(?1)|.)*?\[/quote\])@@g'

またはあなたが言及したように:

perl -pe 's@(\[quote=.*?\](?:(?1)|.)*?\[/quote\])@@g'

を使用すると、perlオプションを追加して複数行の入力を処理できます-0777。の場合、sedコードの前に次のプレフィックスを追加する必要があります。

:0
$!{
  N;b0
}

これにより、入力全体がパターン空間にロードされます。

おすすめ記事