我有一个包含几行不同行的文件。我正在寻找包含(或多或少)这样的模式的行:
\[.*<.*>.*\]
换句话说,我想要<something>
[] 之间的行。示例可能是:
Line with [ <matching>|<pattern>]
A line <that> does[not]<match>[]
But [this[<should>]be matched] too
[match [me] <buddy>]
<> 之间允许的唯一字符是字母数字字符和下划线。
我已经尝试了上面的正则表达式及其惰性版本,但它似乎不起作用。什么是正确的正则表达式?
答案1
如果您的[
,]
对始终匹配,并且您不与 , 交叉[...]
,<...>
并且您grep
支持该-P
选项(就像grep
使用 PCRE 支持构建时的 GNU 一样),您可以执行以下操作:
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'
也就是说,[...]
从内部开始删除对,直到找到<...>
一对中的一个。
(在 Solaris 或非常旧的系统上,删除注释,因为 Solaris sed 只允许在行开头添加注释)。
答案3
这种具有惰性匹配的模式(需要 -P AFAIU)适合我:
grep -P '\[[^\]]*?<.*>.*?\]'
答案4
我想出了以下解决方案:
grep -P '\[[^.\]]*<.*>[^.\[]*\]' filename
换句话说,我们将一对 [ 和 ] 与其之间的一对 < 和 > 进行匹配,并具有以下约束:
- [] 之间不得在 <> 对“[^.\]]*”之前和之后相应地关闭和打开括号。
- <> 内必须至少有一个字符。
该解决方案也比带有惰性量词的正则表达式快得多。