简体   繁体   English

使用正则表达式匹配正则表达式,而不是 JavaScript 中的字符串顺序

[英]match regular expression using regex order, not string order in JavaScript

I'm looking to extract a specific pattern from a string, and if its not there then extract another pattern.我正在寻找从字符串中提取特定模式,如果不存在,则提取另一个模式。

The string in question may have both patterns in any order.有问题的字符串可能以任何顺序具有两种模式。 Regardless of the order, I want the first pattern to take priority.无论顺序如何,我都希望第一个模式优先。

I know I could do this with multiple lines/ match calls but I am wondering if it is possible to do this with a single match call.我知道我可以通过多行/ match调用来做到这一点,但我想知道是否可以通过单个match调用来做到这一点。

var s1 = "hello A123 B456"
var s2 = "hello B123 A456"

I want to capture A### pattern first, and only if its not there , then capture the B### pattern我想先捕获A###模式,并且只有当它不存在时,才捕获B###模式

console.log(s1.match(/((A|B)\d{3})/)[1]); // A123
console.log(s2.match(/((A|B)\d{3})/)[1]); // B123 -- but I want it to capture the A123 first

I guess you can achieve that by anchoring the preferred option to the start of the subject:我想您可以通过将首选选项锚定到主题的开头来实现这一点:

 re = /^.*?(A\\d+)|(B\\d+)/ test = [ "hello A456 B123", "hello B123 A456", "hello A456 zzz", "hello B123 zzz", ]; for (t of test) { m = t.match(re) console.log(t, '=', m[1] || m[2]) }

A drawback is that you have two groups to choose from.一个缺点是您有两个组可供选择。

You can accomplish this with either of the following regex patterns:您可以使用以下任一正则表达式模式来完成此操作:

^(?:.*(A\d{3})|.*(B\d{3}))        # pattern 1
^(?:.*(?=A)|.*(?=B))([AB]\d{3})   # pattern 2

Pattern 1模式一

Regex正则表达式

Pros/Cons: Easy, but uses two capture groups优点/缺点:简单,但使用两个捕获组

^(?:.*(A\d{3})|.*(B\d{3}))

How this works:这是如何工作的:

  • ^ anchors it to the start of the string ^将其锚定到字符串的开头
  • (?:.*(A\\d{3})|.*(B\\d{3})) match either of the following options (?:.*(A\\d{3})|.*(B\\d{3}))匹配以下任一选项
    • .* matches any character (except newline characters) any number of times (it's greedy so it'll match as much as possible) .*匹配任何字符(换行符除外)任意次数(它是贪婪的,所以它会尽可能多地匹配)
    • (A\\d{3}) matches A followed by 3 digits (A\\d{3})匹配A后跟 3 位数字

The second options is the same as the first, but this works with backtracking:第二个选项与第一个选项相同,但这适用于回溯:

^(?:.*(A\d{3})|.*(B\d{3}))

hello B123 A456
^                  # anchor to the start of the string (to the location before the h)
                   # now attempt option 1 of the alternation: .*(A\d{3})
    .*             # match any character any number of times (greedy)
hello B123 A456    # this is what we currently match
                   # now backtrack to find A\d{3}
hello B123 A       # we found A, check to see if \d{3} matches
hello B123 A456    # pattern fulfilled; result you're looking for in group 1

Code代码

 s = ["hello A123 B456","hello B123 A456", "hello B123"] r = /^(?:.*(A\\d{3})|.*(B\\d{3}))/ for (x of s) { m = x.match(r) if (m) console.log(m[1] || m[2]) }


Pattern 2模式2

Regex正则表达式

Pros/Cons: Less comprehensible, but uses only one capture group优点/缺点:不太容易理解,但只使用一个捕获组

^(?:.*(?=A)|.*(?=B))([AB]\d{3})

How this works:这是如何工作的:

  • ^ anchors it to the start of the string ^将其锚定到字符串的开头
  • (?:.*(?=A)|.*(?=B)) match either of the following options (?:.*(?=A)|.*(?=B))匹配以下任一选项
    • .* matches any character (except newline characters) any number of times (it's greedy so it'll match as much as possible) .*匹配任何字符(换行符除外)任意次数(它是贪婪的,所以它会尽可能多地匹配)
    • (?=A) ensures A follows the current position (?=A)确保A跟随当前位置
  • The second alternation is the same as above, but uses (?=B) instead第二个替换与上面相同,但使用(?=B)代替
  • ([AB]\\d{3}) match A or B followed by 3 digits ([AB]\\d{3})匹配AB后跟 3 位数字

Code代码

 s = ["hello A123 B456","hello B123 A456", "hello B123"] r = /^(?:.*(?=A)|.*(?=B))([AB]\\d{3})/ for (x of s) { m = x.match(r) if (m) console.log(m[1]) }

You can also achieve the result with a negative lookahead.您还可以通过负前瞻来实现结果。

 var s1 = "hello A123 B456"; var s2 = "hello B123 A456"; const regex = /A\\d{3}|B\\d{3}(?!.*A\\d{3})/ console.log(s1.match(regex)[0]); console.log(s2.match(regex)[0]);

The above regex is saying, A with 3 digits or B with 3 digits if not followed by A with 3 digits.上面的正则表达式是说, A有 3 位数字或B有 3 位数字,如果后面没有跟有 3 位数字的A

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM