在python中用re.sub替换特殊的标识符模式

时间:2019-06-13 05:00:56

标签: python regex

我是regex的新手,我无法弄清re.sub中的regex替换。

import re

test_cases = [
    "1-Some String #0123",
    "2-Some String #1234-56-a",
    "3-Some String #1234-56A ",
    "4-Some String (Fubar/ #12-345-67A)",
    "5-Some String (Fubar - #12-345.67 A)",
    "6-Some String / #123",
    "7-Some String/#0233",
    "8-Some #1 String/#0233"
    ]

for test in test_cases:
    test = re.sub(r'[/|#][A-Z|a-z|0-9|-]*','', test)
    print(test)

代码应打印:

1-Some String
2-Some String
3-Some String
4-Some String (Fubar)
5-Some String (Fubar)
6-Some String
7-Some String   
8-Some #1 String   

但是,相反,我目前正在获取此信息(其中4,5,8未完全转换):

1-Some String 
2-Some String 
3-Some String  
4-Some String (Fubar )
5-Some String (Fubar - .67 A)
6-Some String  
7-Some String
8-Some  String

4 个答案:

答案 0 :(得分:3)

请尝试以下操作:

import re

test_cases = [
    "1-Some String #0123",
    "2-Some String #1234-56-a",
    "3-Some String #1234-56A ",
    "4-Some String (Fubar/ #12-345-67A)",
    "5-Some String (Fubar - #12-345.67 A)",
    "6-Some String / #123",
    "7-Some String/#0233",
    "8-Some #1 String/#0233"
    ]

for test in test_cases:
    test = re.sub(r'\s*([/#]|- )[\sA-Za-z0-9-#\.]*(?=(\)|$))','', test)
    print(test)

结果:

1-Some String
2-Some String
3-Some String
4-Some String (Fubar)
5-Some String (Fubar)
6-Some String
7-Some String
8-Some #1 String

正则表达式(要删除的子字符串)可以定义为:

  • 以“ /”,“#”或“-”开头
  • 可能在空格之后
  • 由空格,字母数字,连字符,哈希或点组成
  • 通过积极的前瞻方式在“行尾”或“)”锚定

然后正则表达式将如下所示: \s*([/#]|- )[\sA-Za-z0-9-#\.]*(?=(\)|$))

positive lookahead可能需要一些解释。模式(?=regex) 是一个零宽度的断言,表示followed by regex。 好处是匹配的子字符串不包含regex和 您可以将其用作anchor

答案 1 :(得分:2)

另一种选择是使用负超前(?![^#\n\r]*#)仅匹配#的最后一次出现。为了清楚起见,我在方括号之间放置了一个空格[ ]

[ ]*(?:[/-][ ]*)?#(?![^#\n\r]*#)[\da-zA-Z. -]+

说明

  • [ ]*匹配一个空格0次以上
  • (?:[/-][ ]*)?可以选择匹配/-和0+个空格
  • #字面上匹配
  • (?![^#\n\r]*#)负向查找,断言当权利不包含#
  • [\da-zA-Z. -]+匹配1次以上字符类中列出的内容

Regex demo

在替换中,使用一个空字符串。

答案 2 :(得分:1)

分两个步骤进行操作可能更容易:

首先:清除括号中的零件。在'('和一些字母之后,删除所有内容,直到结尾的')'。

第二个:删除行末的多余内容。一行以'#'结尾,后跟2个或多个数字或'/'。可能在'#'或'/'之前有一个空格。

import re

paren_re = re.compile(r"([(][a-zA-Z]+)([^)]*)")

eol_re = re.compile(r"(.*?)\s*(?:#\d\d|/).*")

for line in test_cases:
    result = paren_re.sub(r"\1", line)
    result = eol_re.sub(r"\1", result)

    print(result)

答案 3 :(得分:0)

我无法将它们放入一个正则表达式中,也许有人可以。这是两行解决方案:

import re

test_cases = [
    "1-Some String #0123",
    "2-Some String #1234-56-a",
    "3-Some String #1234-56A ",
    "4-Some String (Fubar/ #12-345-67A)",
    "5-Some String (Fubar - #12-345.67 A)",
    "6-Some String / #123",
    "7-Some String/#0233",
    "8-Some #1 String/#0233"
    ]

for test in test_cases:
    test = re.sub(r'[\/#][\w\s\d\-]*', '', test)
    test = re.sub(r'[\s\.\-\d]+\w+\)', ')', test)
    print(test)

输出:

1-Some String
2-Some String
3-Some String
4-Some String (Fubar)
5-Some String (Fubar)
6-Some String
7-Some String
8-Some

说明:

  1. \w for a-zA-Z
  2. \d for 0-9
  3. \s(空格)
  4. \.表示点
  5. \-

但是我对您的最后一行输出感到困惑,为什么它基于什么输出#1 String?如果您确认可以为该模式编写特定的正则表达式。