首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python regex:替换除年份之外的数字和特殊字符

Python regex:替换除年份之外的数字和特殊字符
EN

Stack Overflow用户
提问于 2017-09-07 15:55:35
回答 3查看 4K关注 0票数 2

我想用空格替换所有非字母字符,不包括1950年到2029年之间的年份。例如:

ab-c 0123 4r. a2017 2010 -> ab c r a 2010

到目前为止,我的尝试是通过负面预测将日期列入黑名单:

代码语言:javascript
运行
复制
re.sub('(?!\b19[5-9][0-9]\b|\b20[0-2][0-9]\b)([^A-Za-z]+)', ' ', string)

由于这不起作用,任何帮助都是非常感谢的!

EN

回答 3

Stack Overflow用户

发布于 2017-09-07 16:00:40

您可以使用一个简单的正则表达式并传递一个函数来检查它是否是一年:

代码语言:javascript
运行
复制
import re

def replace_non_year_numbers(m):
  number = int(m.group(0))
  if 1950 <= number <= 2029:
    return str(number)
  else:
    return ''

print(re.sub('\d+', replace_non_year_numbers, 'ab-c 0123 4r. a2017 2010'))
# 'ab-c  r. a2017 2010'

为了保持正则表达式和逻辑简单,您可以在第二步中删除特殊字符:

代码语言:javascript
运行
复制
only_years = re.sub('\d+', replace_non_year_numbers, 'ab-c 0123 4r. a2017 2010')
no_special_char = re.sub('[^A-Za-z0-9 ]', ' ', only_years)
print(re.sub(' +', ' ', no_special_char))
# ab c r a2017 2010
票数 2
EN

Stack Overflow用户

发布于 2017-09-07 17:02:38

让我们选择您希望保留在结果中的内容。看看正则表达式:

代码语言:javascript
运行
复制
(
  (?<!\w)                       # neg. lookbehind: not a word char
  (1                            # read a '1'
     (?=9[5-9][0-9])            # lookahead: following 3 digits make it
                                #   a year between 1950 and 1999
     [0-9]{3}                   # THEN read these 3 digits
   |                            # - OR -
   2                            # read a '2'
     (?=0[0-2][0-9])            # lookahead: following 3 digits make it
                                #   a year between 2000 and 2029
     [0-9]{3}                   # THEN read these 3 digits 
  )
  |                             # - OR -
  [a-zA-Z]                      # read some letter
)+

在一个线条中:

代码语言:javascript
运行
复制
((?<!\w)(1(?=9[5-9][0-9])[0-9]{3}|2(?=0[0-2][0-9])[0-9]{3})|[a-zA-Z])+

您可以在regex 101上测试它

让我们把它放到一个python脚本中:

代码语言:javascript
运行
复制
$ cat test.py
import re

pattern = r"(?:(?<!\w)(?:1(?=9[5-9][0-9])[0-9]{3}|2(?=0[0-2][0-9])[0-9]{3})|[a-zA-Z])+"

tests = ["ab-c 0123 4r. a2017 2010 a1955 1955 abc"]

for elt in tests:
   matches = re.findall(pattern, elt)
   print ' '.join(matches)

这就给出了:

代码语言:javascript
运行
复制
$ python test.py
ab c r a 2010 a 1955 abc
票数 1
EN

Stack Overflow用户

发布于 2017-09-07 17:24:55

不是很漂亮,但我会使用多个替代:

代码语言:javascript
运行
复制
import re

def check_if_year(m):
  number = int(m.group(0))
  if 1950 <= number <= 2029:
    return str(number)
  else:
    return ' '

s = 'ab-c 0123 4r. a2017 2010 1800'             # Added 1800 for testing
print(s)
print('ab c r a 2010')
t = re.sub(r'[^A-Za-z0-9 ]+', ' ', s)           # Only non-alphanumeric
t = re.sub(r'(?!\b\d{4}\b)(?<!\d)\d+', ' ', t)  # Only numbers that aren't standalone 4 digits
t = re.sub(r'\d+', check_if_year, t)            # Only standalone 4 digits number and test for year
t = re.sub(r' {2,}', ' ', t).strip()            # Clean up extra spaces
print(t)

ideone demo

代码语言:javascript
运行
复制
(?!\b\d{4}\b)(?<!\d)\d+

将匹配任何数字,只要它不是一个独立的4位数字(除了空格或字符串开头/结尾之外没有其他字符),并且我使用(?<!\d),这样它就不会尝试在数字中间进行匹配。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46090928

复制
相关文章

相似问题

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