复数的正则表达式

Regular expression for complex numbers

所以我正在尝试为复数编写正则表达式(就像学习 re 模块的练习)。但我无法让它工作。我希望正则表达式匹配以下形式的字符串:'12+18j'、'-14+45j'、'54'、'-87j' 等等。我的尝试:

import re

num = r'[+-]?(?:\d*.\d+|\d+)'
complex_pattern = rf'(?:(?P<real>{num})|(?P<imag>{num}j))|(?:(?P=real)(?P=imag))'
complex_pattern = re.compile(complex_pattern)

但它并没有真正如我所愿。

m = complex_pattern.fullmatch('1+12j')
m.groupdict()

Out[166]: {'real': None, 'imag': '1+12j'}

其结构背后的原因是我希望输入字符串包含实部或虚部或两者。并且还能够从匹配对象中提取真实和图像组。我尝试了其他方法,它似乎有效,除了它捕获空字符串 (''):

complex_pattern = rf'(?P<real>{num})+(?P<imag>{num}j)+'
complex_pattern = re.compile(complex_pattern)

我想我可以简单地使用 if 来检查空字符串。但我对更纯粹的方式感兴趣,并且想知道为什么第一次实施没有按预期工作。

这对你想要的有用吗?

import re
words= '+122+6766j'
pattern = re.compile(r'((^[-+]?(?P<real>\d+))?[-+]?(?P<img>\d{2,}j?\w)?)')
pattern.fullmatch(words).groupdict()

输出

{'real': '122', 'img': '6766j'}

我建议使用

import re
pattern = r'^(?!$)(?P<real>(?P<sign1>[+-]?)(?P<number1>\d+(?:\.\d+)?))?(?:(?P<imag>(?P<sign2>[+-]?)(?P<number2>\d+(?:\.\d+)?j)))?$'
texts = ['1+12j', '12+18j','-14+45j','54','-87j']
for text in texts:
    match = re.fullmatch(pattern, text)
    if match:
        print(text, '=>', match.groupdict())
    else:
        print(f'{text} did not match!')

Python demo。输出:

1+12j => {'real': '1', 'sign1': '', 'number1': '1', 'imag': '+12j', 'sign2': '+', 'number2': '12j'}
12+18j => {'real': '12', 'sign1': '', 'number1': '12', 'imag': '+18j', 'sign2': '+', 'number2': '18j'}
-14+45j => {'real': '-14', 'sign1': '-', 'number1': '14', 'imag': '+45j', 'sign2': '+', 'number2': '45j'}
54 => {'real': '54', 'sign1': '', 'number1': '54', 'imag': None, 'sign2': None, 'number2': None}
-87j => {'real': '-8', 'sign1': '-', 'number1': '8', 'imag': '7j', 'sign2': '', 'number2': '7j'}

参见regex demo

详情

  • ^ - 字符串开头
  • (?!$) - 此位置不应有字符串结尾(不允许空输入)
  • (?P<real>(?P<sign1>[+-]?)(?P<number1>\d+(?:\.\d+)?))? - “真实”组:
    • (?P<sign1>[+-]?) - 一个可选的 -+ 符号捕获到组“sign1”
    • (?P<number1>\d+(?:\.\d+)?) - 一个或多个数字后跟可选的 . 序列和一个或多个数字捕获到组“number1”
  • (?P<imag>(?P<sign2>[+-]?)(?P<number2>\d+(?:\.\d+)?j))? - 捕获到“imag”组中的可选序列:
    • (?P<sign2>[+-]?) - 一个可选的 -+ 符号捕获到组“sign2”
    • (?P<number2>\d+(?:\.\d+)?j) - 一位或多位数字后跟一个可选序列 . 和一位或多位数字,然后是 j 字符捕获到组“number2”[=52] =]
  • $ - 字符串结尾。

尽管我接受了 回答并认为它非常好。我必须添加一些我注意到的东西。首先,texts 列表中的最后一个字符串没有正确分组(即 '-87j' -> real: -8; imag: 7j)。为了解决这个问题,我建议对他的答案的简化版本进行以下更改:

import re

num = r'[+-]?(?:\d*\.\d+|\d+)'
pattern = rf'(?!$)(?P<real>{num}(?!\d))?(?P<imag>{num}j)?'

texts = ['1+12j', '12+18j','-14+45j','54','-87j']

for text in texts:
    match = re.fullmatch(pattern, text)
    if match:
        print(f'{text:>7} => {match.groupdict()}')
    else:
        print(f'{text:>7} did not match!')

输出:

1+12j   => {'real': '1', 'imag': '+12j'}
 12+18j => {'real': '12', 'imag': '+18j'}
-14+45j => {'real': '-14', 'imag': '+45j'}
     54 => {'real': '54', 'imag': None}
   -87j => {'real': None, 'imag': '-87j'}

这里的重要区别是将 (?!\d) 添加到 'real' 组正则表达式中,以防止像 '-87j' 这样的字符串被拆分为 '-8' 和 '7j'。