【问题标题】:RegEx processing with python使用 python 进行正则表达式处理
【发布时间】:2019-06-28 19:34:37
【问题描述】:

我正在尝试学习 python 并同时使用 NLTK 进行文本分析。

我在文本分析之前使用 python 来清理文本。

给定句子:The target IP was: 127.1.1.100.

我想将其标记为:

["The", "target", "IP", "was", ":","127.1.1.100","."]

保留所有标点符号以重建源文档很重要,但我需要将前导/尾随标点符号分开,以便我可以对单个单词进行文本分析。我编写了以下 python 代码,它运行良好,但看起来有点笨拙。

punct = ['.', ',', ':', ';', '!', '[', ']', '(', ')', '{', '}']
def split_punctuation(sentence)-> list:
    sentwords = sentence.split(" ")
    for i, word in enumerate(sentwords):
        if word_ends_with_punct(word) and len(word) > 1:
            sentwords.pop(i)
            sentwords.insert(i, word[:-1])
            sentwords.insert(i+1, word[-1])
            word = word[:-1]
        if word_starts_with_punct(word) and len(word) > 1:
            sentwords.pop(i)
            sentwords.insert(i, word[0:1])
            sentwords.insert(i+1, word[1:])
            word = word[1:]
    return sentwords

def word_starts_with_punct(w)-> bool:
    for p in punct:
        if w.startswith(p):
            return True
    return False

def word_ends_with_punct(w)->bool:
    for p in punct:
        if w.endswith(p):
            return True
    return False

所以看着 SO,我发现了一个可以满足我要求的正则表达式,有点…… RegEx by Wiktor Stribiżew

re.sub(r'[]!"$%&\'()*+,./:;=#@?[\\^_`{|}~-]+', r' \g<0> ', my_text).strip()

我能够弄清楚发生了什么,但在这种形式中,它分隔了所有标点符号,即使在单词中间也是如此。例如,它将今天的日期从: 6/28/2109"6 / 28 / 2019"

所以我修改为在开始/结束时使用锚标记,但似乎我必须运行它两次,一次用于开始标点符号,另一次用于结束。似乎效率很低,并希望有人可以展示正确的方法来完成此任务。下面的代码是正则表达式版本:

def sep_punct_by_regex(sent)->list :
    words = sent.split(" ")
    new_words = []
    for w in words:
        tmp1 = re.sub(r'^[]!"$/%&\'()*+,.:;=#@?[\\^_`{|}~-]+', r' \g<0> ', w).strip()
        tmp2 = re.sub(r'[]!"$/%&\'()*+,.:;=#@?[\\^_`{|}~-]+$', r' \g<0> ', tmp1).strip()
        t = tmp2.split(" ")
        for x in t:
            new_words.append(x)
    return new_words

注意 tmp1 中的 ^ 和 tmp2 中的 $ 这按原样工作,但目标是在构建时学习,那么我将如何修改 RegEx 以进行单次传递?我在前面尝试了明显的 (^),最后尝试了 $,但它不起作用。

【问题讨论】:

  • 那里有 3 层。字母,一些标点符号,一些数字+一些标点符号。我不认为你可以轻易地标记这个。你必须为此制定一套极端的规则。

标签: python regex nlp


【解决方案1】:

你可以使用

re.findall(r'\b(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\b|[^\W_]+|(?:[^\w\s]|_)+', s)

regex demo

要删除字符串两端的标点符号并从空格中删除,请使用

re.sub(r'^[\W_]+|[\W_]+$', '', s).strip()

所以,它看起来像

s = re.sub(r'^[\W_]+|[\W_]+$', '', s).strip()
oct = r'(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
return re.findall(r'\b{0}(?:\.{0}){{3}}\b|[^\W_]+|(?:[^\w\s]|_)+'.format(oct), s)

详情

  • \b(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\b - 一个IPv4 regex pattern
  • | - 或
  • [^\W_]+ - 一个或多个字母或数字
  • | - 或
  • (?:[^\w\s]|_)+ - 除了单词和空格字符或_之外的一个或多个字符。

【讨论】:

  • 猜我不清楚我的要求,抱歉。我需要检查文档中的每个单词,并删除任何前导/尾随标点符号。不仅仅是 IP。
  • 仍然没有喜悦。输入句子:“Malware Analysis Report (MAR) - 10135536-F”,我期望的是 ["Malware", "Analysis", "Report", "(", "Mar", ")", "-", " 10135536-F"] 我得到的是:['恶意软件','分析','报告','(MAR)','-','10135536-F']。特别是,围绕 MAR 的 () 应该是单独的标记。感谢收看!
  • @GeoffWillis 在特别是my code above returns(Mar) 作为单独的标记。你在测试什么代码?你确定你的要求吗?可能ideone.com/0B3maI 是一个更好的解决方案,但我现在不确定。
  • 抱歉这么密集,但我完全不明白您发布的内容。要求是逐句遍历文档,然后逐字逐句。对于每个单词,确保没有前导/尾随标点符号。我以 IP 为例,还有 (MAR) -> ["(", "MAR", ")"]。我已经发布了我的代码,我认为你想让我代替我的 reg ex。请注意,注释掉的两个正则表达式是您的,并且工作得很好,但试图通过一次。 [链接]github.com/GeoffWillis/TaterPy/blob/master/term_freq_vector/…
  • [link] github.com/GeoffWillis/TaterPy/blob/master/term_freq_vector/… 不知道为什么这个 404 来自这里,浏览器中的剪切粘贴工作正常...
猜你喜欢
  • 2021-07-25
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多