簡體   English   中英

詞法分析或一系列正則表達式以將非結構化文本解析為結構化形式

[英]lexical analyse or series of regular expressions to parse unstructured text into structured form

我正在嘗試編寫一些功能,如Google日歷快速添加功能。 您知道可以在其中輸入以下內容的人:1)2010年9月24日,約翰斯誕辰2)約翰的生日,24/9/10 3)2010年9月24日,約翰·多伊誕辰4)24-9-2010:約翰做生日5)約翰做生日2010年9月24日

它可以弄清楚我們希望日期為24/9/2010的事件將其余材料作為事件文本。

我想做的是python。

我正在考慮一個設計,在其中編寫與上面列出的所有情況匹配的正則表達式並提取日期。 但是我可以找到一種更聰明的方法來解決這個問題。 因為我顯然沒有接受過詞法分析或多種類型的解析器樣式的培訓。 我正在尋找一種解決此問題的好方法。

注意:此處的python代碼不正確! 這只是它看起來的粗略偽代碼。

正則表達式擅長從固定格式的文本中查找和提取數據(例如DD / MM / YYYY日期)。

詞法分析器/解析器對擅長處理結構化但有些可變的格式的數據。 Lexers將文本拆分為標記。 這些令牌是給定類型(數字,字符串等)的信息單元。 解析器采用這一系列令牌,並根據令牌的順序執行某些操作。

查看數據,您會得到一個基本的(主體,動詞,賓語)結構,該結構以不同的組合關系(人,“生日”,日期):

我將使用正則表達式將29/9/10和24-9-2010作為單個令牌處理,並將其作為日期類型返回。 您可能還可以對其他日期執行相同的操作,並使用地圖將9月和9月轉換為9。

然后,您可以將其他所有內容都返回為字符串(由空格分隔)。

然后,您將擁有:

  1. 日期','字符串'生日'
  2. 字符串'birthday'','date
  3. 日期'birthday''of'字符串字符串
  4. 日期':'字符串字符串'生日'
  5. 字符串字符串“生日”日期

注意:“ birthday”,“,”,“:”和“ of”是關鍵字,因此:

class Lexer:
    DATE = 1
    STRING = 2
    COMMA = 3
    COLON = 4
    BIRTHDAY = 5
    OF = 6

    keywords = { 'birthday': BIRTHDAY, 'of': OF, ',': COMMA, ':', COLON }

    def next_token():
        if have_saved_token:
            have_saved_token = False
            return saved_type, saved_value
        if date_re.match(): return DATE, date
        str = read_word()
        if str in keywords.keys(): return keywords[str], str
        return STRING, str

    def keep(type, value):
        have_saved_token = True
        saved_type = type
        saved_value = value

所有除3使用人的所有格形式( 's ,如果最后一個字符是一個輔音, s如果它是一個元音)。 這可能很棘手,因為“ Alexis”可能是“ Alexi”的復數形式,但是由於您限制了復數形式的位置,因此很容易檢測到:

def parseNameInPluralForm():
    name = parseName()
    if name.ends_with("'s"): name.remove_from_end("'s")
    elif name.ends_with("s"): name.remove_from_end("s")
    return name

現在,名字可以是first-namefirst-name last-name (是的,我知道日本會交換first-name last-name ,但是從處理的角度來看,上述問題不需要區分名字和姓氏)。 下面將處理這兩種形式:

def parseName():
    type, firstName = Lexer.next_token()
    if type != Lexer.STRING: raise ParseError()
    type, lastName = Lexer.next_token()
    if type == Lexer.STRING: # first-name last-name
        return firstName + ' ' + lastName
    else:
        Lexer.keep(type, lastName)
        return firstName

最后,您可以使用以下方法處理表格1-5:

def parseBirthday():
    type, data = Lexer.next_token()
    if type == Lexer.DATE: # 1, 3 & 4
        date = data
        type, data = Lexer.next_token()
        if type == Lexer.COLON or type == Lexer.COMMA: # 1 & 4
            person = parsePersonInPluralForm()
            type, data = Lexer.next_token()
            if type != Lexer.BIRTHDAY: raise ParseError()
        elif type == Lexer.BIRTHDAY: # 3
            type, data = Lexer.next_token()
            if type != Lexer.OF: raise ParseError()
            person = parsePerson()
    elif type == Lexer.STRING: # 2 & 5
        Lexer.keep(type, data)
        person = parsePersonInPluralForm()
        type, data = Lexer.next_token()
        if type != Lexer.BIRTHDAY: raise ParseError()
        type, data = Lexer.next_token()
        if type == Lexer.COMMA: # 2
            type, data = Lexer.next_token()
        if type != Lexer.DATE: raise ParseError()
        date = data
    else:
        raise ParseError()
    return person, date

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM