正则表达式:匹配除括号内的所有单词(C#)
Regex: Matching all words EXCEPT those inside of parenthesis (C#)
所以给出:
COLUMN_1, COLUMN_2, COLUMN_3, ((COLUMN_1) AS SOME TEXT) AS COLUMN_4, COLUMN_5
我将如何获得我的比赛:
COLUMN_1
COLUMN_2
COLUMN_3
COLUMN_4
COLUMN_5
我试过:
(?<!(\(.*?\)))(\w+)(,\s*\w+)*?
但我觉得我离基地很远:(我正在使用 regexstorm.net 进行测试。
感谢任何帮助:)
这应该有效:
(?<!\()COLUMN_[\d](?!\))
试一试:https://regex101.com/r/bC4D7n/1
更新:
好的,那试试用这个正则表达式:
[\(]+[\w\s\W]+[\)]+
您需要一个正则表达式来跟踪左括号和右括号,并确保仅当后面有一组平衡的括号(或根本没有括号)时才匹配单词:
Regex regexObj = new Regex(
@"\w+ # Match a word
(?= # only if it's possible to match the following:
(?> # Atomic group (used to avoid catastrophic backtracking):
[^()]+ # Match any characters except parens
| # or
\( (?<DEPTH>) # a (, increasing the depth counter
| # or
\) (?<-DEPTH>) # a ), decreasing the depth counter
)* # any number of times.
(?(DEPTH)(?!)) # Then make sure the depth counter is zero again
$ # at the end of the string.
) # (End of lookahead assertion)",
RegexOptions.IgnorePatternWhitespace);
我试图为 regexstorm.net 提供一个测试 link,但是对于 Whosebug 来说太长了。显然,SO 也不喜欢 URL 缩短器,所以我不能直接 link 这个,但是你应该能够轻松地重新创建 link:http://bit[dot]ly/2cNZS0O
因为你有嵌套的括号,所以事情变得更加棘手。尽管 .NET RegEx 引擎提供了使用堆栈内存的平衡组构造,但我采用了一种更通用的方法,称为递归匹配。
正则表达式:
\((?(?!\(|\)).|(?R))*\)|(\w+)
你只需要在第一个捕获组中。
左边交替的解释:
\( # Match an opening bracket
(?(?!\(|\)) # If next character is not `(` or `)`
. # Then match it
| # Otherwise
(?R) # Recurs whole pattern
)* # As much as possible
\) # Up to corresponding closing bracket
匹配所有单词 除了其中的某些单词 是使用正则表达式可以完成的最困难的练习之一。简单的方法是:构造一个有限自动机,它接受你原来关于它应该接受的字符串的非否定谓词,然后将所有接受状态更改为非接受状态,最后构造一个等价于刚刚构造的自动机的正则表达式.这是一项很难完成的任务,因此最简单的处理方法是 为要否定的谓词构造正则表达式,然后将字符串传递给正则表达式匹配器,如果匹配,则拒绝它.
这样做的主要问题是用计算机很容易做到这一点,但是从自动机描述构造正则表达式是乏味的,而且通常不会给你想要的结果(实际上是一个巨大的结果)。让我用一个例子来说明:
您要求匹配的词,但是从这些词中,您想要的是没有出现在一组词中的词。假设我们想要精确匹配那组单词的自动机,并且假设我们已经匹配了该单词的前 n-1
个字母。这个字符串应该是匹配的,但前提是你接下来没有得到最后一个字母。所以正确的正则表达式应该是一个正则表达式匹配第一个单词的所有字母但最后一个......如此依次,回到第一个字母(很明显,如果你的正则表达式不是以单词的第一个字母开头,它无论如何都不匹配)让我们假设第一个单词是 BEGIN
。一个好的正则表达式匹配不等于 BEGIN
的东西是这样的:
[^B]|B[^E]|BE[^G]|BEG[^I]|BEGI[^N]
另一种情况(使事情更加复杂)是在字符串中不包含单词 BEGIN
的情况下查找与字符串匹配的正则表达式。让我们从相反的谓词中分离出来,找到一个 包含单词 BEGIN
的字符串
^.*BEGIN.*$
然后让我们构造它的有限自动机:
(0)---B--->(1)---E--->(2)---G--->(3)---I--->(4)---N--->((5))
^ \ | | | | ^ \
| | | | | | | |
`-+<-------+<---------+<---------+<---------' `-+
其中双括号表示接受状态。如果你只是
将所有接受状态更改为不接受状态,您将得到一个自动机,它接受第一个不接受的所有字符串,反之亦然。
((0))--B-->((1))--E-->((2))--G-->((3))--I-->((4))--N-->(5)
^ \ | | | | ^ \
| | | | | | | |
`-+<--------+<---------+<---------+<---------' `-+
但是将其转换为简单的正则表达式绝非易事(不信你可以试试)
而且这只是一个词,所以想想如何匹配任何一个词,构造自动机,然后切换每个状态的接受/不接受状态。
对于你的情况,我们有一些事情要处理,前提是你的谓词不等同于我制定的谓词。我的谓词用于匹配其中有一个词的表达式(这是构想正则表达式的目标),但你的谓词 用于匹配你的正则表达式中的组。如果你试试我的例子,你会发现一个简单的字符串 ""
(空字符串)匹配第二个正则表达式,因为起始 ((0))
状态是接受状态(好吧,空字符串不包含单词 BEGIN
),但您希望您的正则表达式匹配单词(而 ""
不是单词)所以我们首先需要定义什么是您的单词并构造匹配的正则表达式一句话:
[a-zA-Z][a-zA-Z]*
应该是个不错的人选。它应该进入这样的自动机定义:
(0)---[a-zA-Z]--->((1))---[a-zA-Z]--.
^ \ | ^ |
| * * | |
`--+<-------------' `-------------'
并且您希望自动机接受两者(1-必须是一个词,2-不在词集中)(不在词集中等同于不是第一个词,并且不是第二个也不是第三个......你可以通过首先构造一个自动机来构造它,如果它是第一个单词,or第二个,or第三个,...然后取反)构造第一个自动机,第二个然后构造一个匹配both的自动机。这对于计算机来说很容易用自动机来完成,但对人来说却不是。
正如我所说,从正则表达式构造自动机对计算机来说是一件简单直接的事情,但对人来说却不是。从自动机构造正则表达式也是如此,但它会产生巨大的正则表达式,并且由于这个问题,大多数实现都会导致扩展运算符的实现,如果某些正则表达式不匹配,则相反。
结论
使用否定运算符可以得到关于正则表达式接受器必须接受的字符串集的相反谓词,或者只是简单地构造一个正则表达式来做简单的事情并使用布尔代数来完成剩下的事情。
所以给出:
COLUMN_1, COLUMN_2, COLUMN_3, ((COLUMN_1) AS SOME TEXT) AS COLUMN_4, COLUMN_5
我将如何获得我的比赛:
COLUMN_1
COLUMN_2
COLUMN_3
COLUMN_4
COLUMN_5
我试过:
(?<!(\(.*?\)))(\w+)(,\s*\w+)*?
但我觉得我离基地很远:(我正在使用 regexstorm.net 进行测试。
感谢任何帮助:)
这应该有效:
(?<!\()COLUMN_[\d](?!\))
试一试:https://regex101.com/r/bC4D7n/1
更新:
好的,那试试用这个正则表达式:
[\(]+[\w\s\W]+[\)]+
您需要一个正则表达式来跟踪左括号和右括号,并确保仅当后面有一组平衡的括号(或根本没有括号)时才匹配单词:
Regex regexObj = new Regex(
@"\w+ # Match a word
(?= # only if it's possible to match the following:
(?> # Atomic group (used to avoid catastrophic backtracking):
[^()]+ # Match any characters except parens
| # or
\( (?<DEPTH>) # a (, increasing the depth counter
| # or
\) (?<-DEPTH>) # a ), decreasing the depth counter
)* # any number of times.
(?(DEPTH)(?!)) # Then make sure the depth counter is zero again
$ # at the end of the string.
) # (End of lookahead assertion)",
RegexOptions.IgnorePatternWhitespace);
我试图为 regexstorm.net 提供一个测试 link,但是对于 Whosebug 来说太长了。显然,SO 也不喜欢 URL 缩短器,所以我不能直接 link 这个,但是你应该能够轻松地重新创建 link:http://bit[dot]ly/2cNZS0O
因为你有嵌套的括号,所以事情变得更加棘手。尽管 .NET RegEx 引擎提供了使用堆栈内存的平衡组构造,但我采用了一种更通用的方法,称为递归匹配。
正则表达式:
\((?(?!\(|\)).|(?R))*\)|(\w+)
你只需要在第一个捕获组中。
左边交替的解释:
\( # Match an opening bracket
(?(?!\(|\)) # If next character is not `(` or `)`
. # Then match it
| # Otherwise
(?R) # Recurs whole pattern
)* # As much as possible
\) # Up to corresponding closing bracket
匹配所有单词 除了其中的某些单词 是使用正则表达式可以完成的最困难的练习之一。简单的方法是:构造一个有限自动机,它接受你原来关于它应该接受的字符串的非否定谓词,然后将所有接受状态更改为非接受状态,最后构造一个等价于刚刚构造的自动机的正则表达式.这是一项很难完成的任务,因此最简单的处理方法是 为要否定的谓词构造正则表达式,然后将字符串传递给正则表达式匹配器,如果匹配,则拒绝它.
这样做的主要问题是用计算机很容易做到这一点,但是从自动机描述构造正则表达式是乏味的,而且通常不会给你想要的结果(实际上是一个巨大的结果)。让我用一个例子来说明:
您要求匹配的词,但是从这些词中,您想要的是没有出现在一组词中的词。假设我们想要精确匹配那组单词的自动机,并且假设我们已经匹配了该单词的前 n-1
个字母。这个字符串应该是匹配的,但前提是你接下来没有得到最后一个字母。所以正确的正则表达式应该是一个正则表达式匹配第一个单词的所有字母但最后一个......如此依次,回到第一个字母(很明显,如果你的正则表达式不是以单词的第一个字母开头,它无论如何都不匹配)让我们假设第一个单词是 BEGIN
。一个好的正则表达式匹配不等于 BEGIN
的东西是这样的:
[^B]|B[^E]|BE[^G]|BEG[^I]|BEGI[^N]
另一种情况(使事情更加复杂)是在字符串中不包含单词 BEGIN
的情况下查找与字符串匹配的正则表达式。让我们从相反的谓词中分离出来,找到一个 包含单词 BEGIN
的字符串
^.*BEGIN.*$
然后让我们构造它的有限自动机:
(0)---B--->(1)---E--->(2)---G--->(3)---I--->(4)---N--->((5))
^ \ | | | | ^ \
| | | | | | | |
`-+<-------+<---------+<---------+<---------' `-+
其中双括号表示接受状态。如果你只是 将所有接受状态更改为不接受状态,您将得到一个自动机,它接受第一个不接受的所有字符串,反之亦然。
((0))--B-->((1))--E-->((2))--G-->((3))--I-->((4))--N-->(5)
^ \ | | | | ^ \
| | | | | | | |
`-+<--------+<---------+<---------+<---------' `-+
但是将其转换为简单的正则表达式绝非易事(不信你可以试试)
而且这只是一个词,所以想想如何匹配任何一个词,构造自动机,然后切换每个状态的接受/不接受状态。
对于你的情况,我们有一些事情要处理,前提是你的谓词不等同于我制定的谓词。我的谓词用于匹配其中有一个词的表达式(这是构想正则表达式的目标),但你的谓词 用于匹配你的正则表达式中的组。如果你试试我的例子,你会发现一个简单的字符串 ""
(空字符串)匹配第二个正则表达式,因为起始 ((0))
状态是接受状态(好吧,空字符串不包含单词 BEGIN
),但您希望您的正则表达式匹配单词(而 ""
不是单词)所以我们首先需要定义什么是您的单词并构造匹配的正则表达式一句话:
[a-zA-Z][a-zA-Z]*
应该是个不错的人选。它应该进入这样的自动机定义:
(0)---[a-zA-Z]--->((1))---[a-zA-Z]--.
^ \ | ^ |
| * * | |
`--+<-------------' `-------------'
并且您希望自动机接受两者(1-必须是一个词,2-不在词集中)(不在词集中等同于不是第一个词,并且不是第二个也不是第三个......你可以通过首先构造一个自动机来构造它,如果它是第一个单词,or第二个,or第三个,...然后取反)构造第一个自动机,第二个然后构造一个匹配both的自动机。这对于计算机来说很容易用自动机来完成,但对人来说却不是。
正如我所说,从正则表达式构造自动机对计算机来说是一件简单直接的事情,但对人来说却不是。从自动机构造正则表达式也是如此,但它会产生巨大的正则表达式,并且由于这个问题,大多数实现都会导致扩展运算符的实现,如果某些正则表达式不匹配,则相反。
结论
使用否定运算符可以得到关于正则表达式接受器必须接受的字符串集的相反谓词,或者只是简单地构造一个正则表达式来做简单的事情并使用布尔代数来完成剩下的事情。