我需要写一个让我摸不着头脑的正则表达式。从本质上讲,我有一列数据,其中包括以下值:
ACME Corp 123
Corp 742 ACME
Random Text
Broadway 1785 FB我想要做的是查找术语ACME和BROADWAY。如果其中任何一个存在,请保留它,并且只保留它。如果两者都不存在,则保留整个字符串。因此上面这一列将变为:
ACME
ACME
Random Text
Broadway这有意义吗?
发布于 2017-09-27 02:30:18
简介
这让我抓狂了一阵子。我确信正则表达式本身不是这个问题的最佳解决方案,但是,这是您的解决方案。
代码
正则表达式
^.*?((?(?=.*?(\b(?:broadway|acme)\b).*?)\2|.*)).*?$替换
组1如下所示。相反,您可以从匹配数组中收集组1变量,但如果您想要替换,可以使用以下方法
$1结果
注意:我添加了另一个字符串作为测试,以确保如果将任何一个单词放在行的中间,它仍然会捕捉到它。
输入
ACME Corp 123
Corp 742 ACME
Some ACME some
Random Text
Broadway 1785 FB输出
ACME
ACME
ACME
Random Text
Broadway解释
使用不区分大小写的i和多行m标志:
^断言line.*?开头的位置匹配任意字符任意次,但只要possible((?(?=.*?(\b(?:broadway|acme)\b).*?)\2|.*))分成多个部分()就捕获下面的(?(?=...)) If/else statement(?=.*?(\b(?:broadway|acme)\b).*?)正向先行匹配后面的.*?任意字符任意次数,但是少到possible(...)捕获以下内容进入捕获组2\b(?:broadway|acme)\b词边界,后跟broadway或acme,后面跟一个单词boundary.*?任何字符的次数都是任意的,但次数和possible一样少
- `\2` If the if/else statement is **true** (it matches the above), capture the group (as described above) - which is simply `broadway` or `acme`
- `.*` If the if/else statement is **false**, match any character any number of times.*?与任意字符匹配任意次,但与行尾的possible$ Assert position一样少--
更新
既然我的回答已经引起了相当大的关注,我想我应该修改一下。不确定关注的是正则表达式中的if/else,还是更多地与示例输入中OP的预期结果相关。
如果/否则
我需要指出的是,正则表达式if/else的通用格式如下(并且只有某些正则表达式引擎支持这个标记):
(?(?=condition)x|y)在上面的正则表达式中(?=condition)可以是你想要的任何东西(你也可以使用负lookaheads或lookbehinds,甚至是它们的组合。
替代方案
如果并不是所有语言都支持regex中的/else,那么您可以使用一种变通方法:
# optional group, fallback to match all (x?y)
^(?:.*?\b(broadway|acme)\b)?.*
# alternation (x||y)
^(?:.*?\b(broadway|acme)\b|.*)
# tempered greedy token alternation
^(?:(?!\b(?:broadway|acme)\b).|(broadway|acme))+
# same as above reusing capture group 1’s definition
^(?:(?!\b(broadway|acme)\b).|((?1)))+发布于 2017-09-27 03:24:44
一个足以解决这个问题的正则表达式是:
^(?(?=(acme|broadway))\1|[\w\s])+?$为什么这就足够了?如果您的输入字符串中包含acme或broadway,则组1将捕获该值。如果group 1为空,则完全匹配结果。
细目:
^(? # start conditional
(?= # lookahead for position before
( # group 1 start
acme|broadway # either "acme" or "broadway"
) # group 1 end
)
\1 # if found, then match group 1
| # else
[\w\s] # read a word char or space
)+?$ # do this over and over again, non-greedy 你可以在example 1上看一下
发布于 2020-07-15 14:42:29
另一种不使用先行断言的解决方案
^.*(ACME|Broadway).*$解释:
^ # beginning of the string
.* # match any character any number of times
( # start of capture group
ACME|Broadway # if the input string has ACME or Broadway capture in the memory($1)
) # end of the capture group
.* # match any character any number of times
$ # end of the stringhttps://regex101.com/r/mDCL5g/1
此外,您还可以在Javascript中使用相同的正则表达式,如下所示
'ACME Corp 123'.replace(/^.*(ACME|Broadway).*$/, '$1'); // ACME
'Corp 742 ACME'.replace(/^.*(ACME|Broadway).*$/, '$1'); // ACME
'Random Text'.replace(/^.*(ACME|Broadway).*$/, '$1'); // Random Text
'Broadway 1785 FB'.replace(/^.*(ACME|Broadway).*$/, '$1'); // Broadway https://stackoverflow.com/questions/46432854
复制相似问题