条件匹配(Conditional Matching)

2024-06-24 20:55:57 290
条件匹配是一种非常强大的正则表达式特性,用于根据特定条件选择不同的匹配模式。

基本语法

条件匹配的基本语法是:

(?(condition)true-pattern|false-pattern)
  • condition:要检查的条件,可以是一个捕获组的编号或名称,也可以是一个零宽度断言。
  • true-pattern:当条件为真时要使用的模式。
  • false-pattern:当条件为假时要使用的模式。

示例

根据捕获组是否匹配进行条件匹配

示例

(?(1)foo|bar)

如果捕获组 1 匹配成功,则匹配 foo,否则匹配 bar

解释

  • (?(1)foo|bar):条件部分检查捕获组 1 是否匹配成功。
  • 如果捕获组 1 匹配成功,则整个表达式匹配 foo
  • 如果捕获组 1 不匹配,则整个表达式匹配 bar

实际应用

  • 匹配一个单词后面跟着不同的内容,具体取决于前面是否捕获到了某个模式。

使用零宽度断言进行条件匹配

示例

当条件是一个零宽度断言时:

(?(?=foo)bar|baz)

如果当前位置的右边是 foo,则匹配 bar,否则匹配 baz

解释

  • (?(?=foo)bar|baz):条件部分检查当前位置的右边是否有 foo
  • 如果右边是 foo,则整个表达式匹配 bar
  • 如果右边不是 foo,则整个表达式匹配 baz

实际应用

  • 动态选择匹配内容,基于当前位置的上下文信息。

代码示例

Python 示例

使用捕获组的条件匹配

import re

pattern = r'(\d)?(?(1)\d{3}|\w{3})'
test_string_1 = '1234'
test_string_2 = 'abc'

# 测试第一个字符串
match_1 = re.match(pattern, test_string_1)
if match_1:
    print(f"Matched: {match_1.group(0)}")  # 输出: 1234

# 测试第二个字符串
match_2 = re.match(pattern, test_string_2)
if match_2:
    print(f"Matched: {match_2.group(0)}")  # 输出: abc

使用零宽度断言的条件匹配

import re

pattern = r'(?(?=\d)\d{3}|\w{3})'
test_string_1 = '123'
test_string_2 = 'abc'

# 测试第一个字符串
match_1 = re.match(pattern, test_string_1)
if match_1:
    print(f"Matched: {match_1.group(0)}")  # 输出: 123

# 测试第二个字符串
match_2 = re.match(pattern, test_string_2)
if match_2:
    print(f"Matched: {match_2.group(0)}")  # 输出: abc

JavaScript 示例

使用捕获组的条件匹配

const pattern = /(\d)?(?(1)\d{3}|\w{3})/;
const testString1 = '1234';
const testString2 = 'abc';

// 测试第一个字符串
let match1 = testString1.match(pattern);
if (match1) {
    console.log(`Matched: ${match1[0]}`);  // 输出: 1234
}

// 测试第二个字符串
let match2 = testString2.match(pattern);
if (match2) {
    console.log(`Matched: ${match2[0]}`);  // 输出: abc
}

使用零宽度断言的条件匹配

const pattern = /(?(?=\d)\d{3}|\w{3})/;
const testString1 = '123';
const testString2 = 'abc';

// 测试第一个字符串
let match1 = testString1.match(pattern);
if (match1) {
    console.log(`Matched: ${match1[0]}`);  // 输出: 123
}

// 测试第二个字符串
let match2 = testString2.match(pattern);
if (match2) {
    console.log(`Matched: ${match2[0]}`);  // 输出: abc
}

复杂条件匹配示例

示例

(\d{3})?(?(1)-\d{4}|\d{3}-\d{4})

如果捕获组 1 匹配了 3 位数字,则匹配 - 后跟 4 位数字,否则匹配 3 位数字后跟 - 再跟 4 位数字。

解释

  • (\d{3})?:可选的 3 位数字,作为捕获组 1。
  • (?(1)-\d{4}|\d{3}-\d{4}):如果捕获组 1 匹配了,则匹配 - 后跟 4 位数字;否则匹配 3 位数字后跟 - 再跟 4 位数字。

代码示例

  • Python

    import re
    
    pattern = r'(\d{3})?(?(1)-\d{4}|\d{3}-\d{4})'
    test_string_1 = '123-4567'
    test_string_2 = '456-7890'
    test_string_3 = '4567'
    
    matches_1 = re.fullmatch(pattern, test_string_1)
    matches_2 = re.fullmatch(pattern, test_string_2)
    matches_3 = re.fullmatch(pattern, test_string_3)
    
    print(matches_1.group(0) if matches_1 else 'No match')  # 输出: 123-4567
    print(matches_2.group(0) if matches_2 else 'No match')  # 输出: 456-7890
    print(matches_3.group(0) if matches_3 else 'No match')  # 输出: 4567
    
  • JavaScript

    const pattern = /(\d{3})?(?(1)-\d{4}|\d{3}-\d{4})/;
    const testString1 = '123-4567';
    const testString2 = '456-7890';
    const testString3 = '4567';
    
    console.log(testString1.match(pattern)[0]);  // 输出: 123-4567
    console.log(testString2.match(pattern)[0]);  // 输出: 456-7890
    console.log(testString3.match(pattern)[0]);  // 输出: 4567