匹配不被括号包围的下划线的正则表达式?

3

如果你正在使用.NET,那么你可能会发现www.lastdomainnameonearth.com是一个有用的测试工具。 - strongopinions
5个回答

5

试试这个:

_[^\]]|[^[]_

它由_[^\]] (下划线和不是])和[^[]_ (不是[和下划线)交替组成。

或者,如果您想使用前后查找断言来确实只匹配下划线而不是周围字符:

_(?=[^\]])|_(?<=[^[]_)

这个模式匹配任何一个下划线,但该下划线后面不能是 ](使用正向先行断言:(?=[^\]]))或者该下划线前面不能是 [(使用负向后行断言:(?<=[^[]_))。这两个条件可以组合使用:

_(?:(?=[^\]])|(?<=[^[]_))

这很接近了,除了它匹配了一个额外的字符,而不仅仅是下划线。我尝试修改它使用前瞻,但它并不适用于所有情况。(?=[^]])|(?=[^[]) - Moskie
测试字符串:"test[_]test [test test[test test]test test] test_test"。发现3个匹配项,应该找到5个。 - Kevin Albrecht
@Moskie:在后一种情况下,您需要使用“向后查找断言”。 - Gumbo
我认为这就是它:_(?=[^]])|(?<=[^[])_ - Moskie
@Moskie:最好使用_(?=[^\]])|_(?<=_[^[]) - Gumbo
显示剩余2条评论

2
_(?!\](?<=\[_\]))

如果下划线后面没有紧跟着一个闭合括号,否定前瞻会立即成功。否则,它将执行回顾操作,以查找下划线是否还是由开放括号先行。您可以将“_]”替换为点以明确表明此时您只对开放括号感兴趣。
_(?!\](?<=\[..))

如果您愿意,可以先进行向后查找:

_(?<!\[_(?=\]))

重要的是第二个lookaround必须嵌套在第一个里面,以实现“NOT (x AND y)”的语义。在EditPad Pro中测试它,会将这些字符串中除最后一个外的所有下划线都匹配:
test_test
test[_test
test_]
_]Test
Test[_
test[_]test

编辑:这里有一个更易读的版本:

(?<!\[)_|_(?!\])

我喜欢嵌套环视版本的原因是它只有在找到下划线时才会执行操作。除非正则表达式引擎足够聪明以优化掉它,否则这个“(NOT x)OR(NOT y)”版本将在每个位置进行负回顾。

使用字符串 "test[_]test [test test[test test]test test] test_test" 进行测试,发现 0 个结果,应该找到 5 个。 - Kevin Albrecht
我已经在.NET和Java中进行了测试,并得到了相同的结果:前五个字符串匹配,最后一个字符串不匹配。 - Alan Moore

1

我不了解 .Net,但正则表达式应该由两部分组成,一部分匹配除括号和下划线以外的任何字符,另一部分则相反:

[^\[](_)|(_)[^\]]

编辑:刚注意到您需要添加下划线在开头或结尾的情况:

[^\[](_)|(_)[^\]]|^_|_$

没有起作用:test[_test(我在这里使用RegEx测试器进行测试:http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx) - Moskie
嗨,Moskie。如果没有选中任何选项,这个正则表达式可以匹配字符串“test[_test”中的下划线。 - neoneye

1

((?|(?!]))

这段代码使用了负向预测/回顾(而不是正向预测/回顾和排除字符)。


0

尝试

^.*(\[_[^\]])|([^\[]_\])|([^\[]_[^\]]).*$

编辑:现在处理

test_test

未经测试,但是可以理解为:任何字符串后面跟着要么[_再加上任意一个非]字符或者任意一个非[字符再加上_]

请注意,这种情况可能会失败:

_]Test
Test[_

我不知道这对你是否是个问题?

已经成功测试了你提供的所有例子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接