区切り記号間の正規表現の一致

区切り記号間の正規表現の一致

複数行を含むファイルがあります。次のパターンを含む行を探しています。

\[.*<.*>.*\]

つまり、<something>[]の間の行が必要です。例は次のとおりです。

Line with [ <matching>|<pattern>]
A line <that> does[not]<match>[]
But [this[<should>]be matched] too
[match [me] <buddy>]

<>の間に許可される唯一の文字は英数字と下線です。

上記の正規表現と怠惰なバージョンを試しましたが、うまくいかないようです。正しい正規表現は何ですか?

答え1

[]ペアが常に一致し、交差しておらず、その[...]オプションをサポートしている<...>場合(PCREサポートでビルドするときにGNUが行うように)、次のことができます。grep-Pgrep

grep -P '>(?!((?:[^]]|\[(?1)\])*)$)'

つまり、>次を探しています。いいえその後、一致する[...]ペアだけが出ます。 PCREの再帰的一致メカニズムを使用してください(?1)

答え2

POSIXlyでは、次のことができますsed

sed  '
  h; # make a copy of the pristine line on the hold space
  :1
    /\[[^]]*<[^]]*>[^]]*]/{
      # found a [...<x>...]
      g; # retrieve our saved copy and branch off
      b
    }
    s/\[\([^]]*\)]/\1/g; # remove inner [...]s
    # and loop if that s command was successful
  t1
  # no [...] left to remove, discard this line.
  d'

つまり、ペアの1つが見つかる[...]まで内側からペアが削除されます。<...>

(Solaris または非常に古いシステムでは、Solaris sed は行の先頭でのみコメントを受け入れるため、コメントを削除してください.)

答え3

遅延一致(-P AFAIUが必要)を含むこのパターンは私に適しています。

grep -P '\[[^\]]*?<.*>.*?\]'

答え4

私は次の解決策を思いついた。

grep -P '\[[^.\]]*<.*>[^.\[]*\]' filename

つまり、次の制約に従って[と]のペアを<と>のペアと一致させます。

  1. []は<>の前に来てはいけません。 "[^.\]]*"の前後には角かっこを閉じるか開けます。
  2. <>の中には少なくとも1つの文字が必要です。

このソリューションは、怠惰な数量子を使用する正規表現よりもはるかに高速です。

関連情報