首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >REGEX IF THEN ELSE语句

REGEX IF THEN ELSE语句
EN

Stack Overflow用户
提问于 2017-09-27 01:49:42
回答 4查看 32.9K关注 0票数 8

我需要写一个让我摸不着头脑的正则表达式。从本质上讲,我有一列数据,其中包括以下值:

代码语言:javascript
复制
ACME Corp 123
Corp 742 ACME
Random Text
Broadway 1785 FB

我想要做的是查找术语ACMEBROADWAY。如果其中任何一个存在,请保留它,并且只保留它。如果两者都不存在,则保留整个字符串。因此上面这一列将变为:

代码语言:javascript
复制
ACME
ACME
Random Text
Broadway

这有意义吗?

EN

回答 4

Stack Overflow用户

发布于 2017-09-27 02:30:18

简介

这让我抓狂了一阵子。我确信正则表达式本身不是这个问题的最佳解决方案,但是,这是您的解决方案。

代码

See this code in use here

正则表达式

代码语言:javascript
复制
^.*?((?(?=.*?(\b(?:broadway|acme)\b).*?)\2|.*)).*?$

替换

组1如下所示。相反,您可以从匹配数组中收集组1变量,但如果您想要替换,可以使用以下方法

代码语言:javascript
复制
$1

结果

注意:我添加了另一个字符串作为测试,以确保如果将任何一个单词放在行的中间,它仍然会捕捉到它。

输入

代码语言:javascript
复制
ACME Corp 123
Corp 742 ACME
Some ACME some
Random Text
Broadway 1785 FB

输出

代码语言:javascript
复制
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词边界,后跟broadwayacme,后面跟一个单词boundary
        • .*?任何字符的次数都是任意的,但次数和possible

一样少

代码语言:javascript
复制
    - `\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的通用格式如下(并且只有某些正则表达式引擎支持这个标记):

代码语言:javascript
复制
(?(?=condition)x|y)

在上面的正则表达式中(?=condition)可以是你想要的任何东西(你也可以使用负lookaheads或lookbehinds,甚至是它们的组合。

替代方案

如果并不是所有语言都支持regex中的/else,那么您可以使用一种变通方法:

代码语言:javascript
复制
# 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)))+
票数 16
EN

Stack Overflow用户

发布于 2017-09-27 03:24:44

一个足以解决这个问题的正则表达式是:

代码语言:javascript
复制
 ^(?(?=(acme|broadway))\1|[\w\s])+?$

为什么这就足够了?如果您的输入字符串中包含acmebroadway,则组1将捕获该值。如果group 1为空,则完全匹配结果。

细目:

代码语言:javascript
复制
 ^(?                          # 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上看一下

票数 3
EN

Stack Overflow用户

发布于 2020-07-15 14:42:29

另一种不使用先行断言的解决方案

代码语言:javascript
复制
^.*(ACME|Broadway).*$

解释:

代码语言:javascript
复制
^                     # 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 string

https://regex101.com/r/mDCL5g/1

此外,您还可以在Javascript中使用相同的正则表达式,如下所示

代码语言: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 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46432854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档