1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        再見,正則表達式

        共 3331字,需瀏覽 7分鐘

         ·

        2020-09-07 00:52



        從一段指定的字符串中,取得期望的數(shù)據(jù),正常人都會想到正則表達式吧?

        寫過正則表達式的人都知道,正則表達式入門不難,寫起來也容易。

        但是正則表達式幾乎沒有可讀性可言,維護起來,真的會讓人抓狂,別以為這段正則是你寫的就可以駕馭它,過個一個月你可能就不認識它了。

        完全可以說,天下苦正則久矣。

        今天給你介紹一個好東西,可以讓你擺脫正則的噩夢,那就是 Python 中一個非常冷門的庫 -- ?parse

        1. 真實案例

        拿一個最近使用 parse 的真實案例來舉例說明。

        下面是 ovs 一個條流表,現(xiàn)在我需要收集提取一個虛擬機(網(wǎng)口)里有多少流量、多少包流經(jīng)了這條流表。也就是每個 in_port 對應的 n_bytes、n_packets 的值 。

        cookie=0x9816da8e872d717d,?duration=298506.364s,?table=0,?n_packets=480,?n_bytes=20160,?priority=10,ip,in_port="tapbbdf080b-c2"?actions=NORMAL

        如果是你,你會怎么做呢?

        先以逗號分隔開來,再以等號分隔取出值來?

        你不防可以嘗試一下,寫出來的代碼應該和我想象的一樣,沒有一絲美感而言。

        我來給你展示一下,我是怎么做的?

        可以看到,我使用了一個叫做 parse 的第三方包,是需要自行安裝的

        $?python?-m?pip?install?parse

        從上面這個案例中,你應該能感受到 parse 對于解析規(guī)范的字符串,是非常強大的。

        2. parse 的結果

        parse 的結果只有兩種結果:

        1. 沒有匹配上,parse 的值為None
        >>>?parse("halo",?"hello")?is?None
        True
        >>>
        1. 如果匹配上,parse 的值則 為 Result 實例
        >>>?parse("hello",?"hello?world")
        >>>?parse("hello",?"hello")

        >>>?

        如果你編寫的解析規(guī)則,沒有為字段定義字段名,也就是匿名字段, Result 將是一個 類似 list 的實例,演示如下:

        >>>?profile?=?parse("I?am?{},?{}?years?old,?{}",?"I?am?Jack,?27?years?old,?male")
        >>>?profile
        'Jack',?'27',?'male')?{}>
        >>>?profile[0]
        'Jack'
        >>>?profile[1]
        '27'
        >>>?profile[2]
        'male'

        而如果你編寫的解析規(guī)則,為字段定義了字段名, Result 將是一個 類似 字典 的實例,演示如下:

        >>>?profile?=?parse("I?am?{name},?{age}?years?old,?{gender}",?"I?am?Jack,?27?years?old,?male")
        >>>?profile
        'gender':?'male',?'age':?'27',?'name':?'Jack'}>
        >>>?profile['name']
        'Jack'
        >>>?profile['age']
        '27'
        >>>?profile['gender']
        'male'

        3. 重復利用 pattern

        和使用 re 一樣,parse 同樣支持 pattern 復用。

        >>>?from?parse?import?compile
        >>>?
        >>>?pattern?=?compile("I?am?{},?{}?years?old,?{}")
        >>>?pattern.parse("I?am?Jack,?27?years?old,?male")
        'Jack',?'27',?'male')?{}>
        >>>?
        >>>?pattern.parse("I?am?Tom,?26?years?old,?male")
        'Tom',?'26',?'male')?{}>

        4. 類型轉化

        從上面的例子中,你應該能注意到,parse 在獲取年齡的時候,變成了一個"27" ,這是一個字符串,有沒有一種辦法,可以在提取的時候就按照我們的類型進行轉換呢?

        你可以這樣寫。

        >>>?from?parse?import?parse
        >>>?profile?=?parse("I?am?{name},?{age:d}?years?old,?{gender}",?"I?am?Jack,?27?years?old,?male")
        >>>?profile
        'gender':?'male',?'age':?27,?'name':?'Jack'}>
        >>>?type(profile["age"])
        'int'>

        除了將其轉為 整型,還有其他格式嗎?

        內(nèi)置的格式還有很多,比如

        匹配時間

        >>>?parse('Meet?at?{:tg}',?'Meet?at?1/2/2011?11:00?PM')
        2011,?2,?1,?23,?0),)?{}>

        更多類型請參考官方文檔:

        TypeCharacters MatchedOutput
        lLetters (ASCII)str
        wLetters, numbers and underscorestr
        WNot letters, numbers and underscorestr
        sWhitespacestr
        SNon-whitespacestr
        dDigits (effectively integer numbers)int
        DNon-digitstr
        nNumbers with thousands separators (, or .)int
        %Percentage (converted to value/100.0)float
        fFixed-point numbersfloat
        FDecimal numbersDecimal
        eFloating-point numbers with exponent e.g. 1.1e-10, NAN (all case insensitive)float
        gGeneral number format (either d, f or e)float
        bBinary numbersint
        oOctal numbersint
        xHexadecimal numbers (lower and upper case)int
        tiISO 8601 format date/time e.g. 1972-01-20T10:21:36Z (“T” and “Z” optional)datetime
        teRFC2822 e-mail format date/time e.g. Mon, 20 Jan 1972 10:21:36 +1000datetime
        tgGlobal (day/month) format date/time e.g. 20/1/1972 10:21:36 AM +1:00datetime
        taUS (month/day) format date/time e.g. 1/20/1972 10:21:36 PM +10:30datetime
        tcctime() format date/time e.g. Sun Sep 16 01:03:52 1973datetime
        thHTTP log format date/time e.g. 21/Nov/2011:00:07:11 +0000datetime
        tsLinux system log format date/time e.g. Nov 9 03:37:44datetime
        ttTime e.g. 10:21:36 PM -5:30time

        5. 提取時去除空格

        去除兩邊空格

        >>>?parse('hello?{}?,?hello?python',?'hello?????world????,?hello?python')
        '????world???',)?{}>
        >>>?
        >>>?
        >>>?parse('hello?{:^}?,?hello?python',?'hello?????world????,?hello?python')
        'world',)?{}>

        去除左邊空格

        >>>?parse('hello?{:>}?,?hello?python',?'hello?????world????,?hello?python')
        'world???',)?{}>

        去除右邊空格

        >>>?parse('hello?{:<}?,?hello?python',?'hello?????world????,?hello?python')
        '????world',)?{}>

        6. 大小寫敏感開關

        Parse 默認是大小寫不敏感的,你寫 hello 和 HELLO 是一樣的。

        如果你需要區(qū)分大小寫,那可以加個參數(shù),演示如下:

        >>>?parse('SPAM',?'spam')

        >>>?parse('SPAM',?'spam')?is?None
        False
        >>>?parse('SPAM',?'spam',?case_sensitive=True)?is?None
        True

        7. 匹配字符數(shù)

        精確匹配:指定最大字符數(shù)

        >>>?parse('{:.2}{:.2}',?'hello')??#?字符數(shù)不符
        >>>?
        >>>?parse('{:.2}{:.2}',?'hell')???#?字符數(shù)相符
        'he',?'ll')?{}>

        模糊匹配:指定最小字符數(shù)

        >>>?parse('{:.2}{:2}',?'hello')?
        'h',?'ello')?{}>
        >>>?
        >>>?parse('{:2}{:2}',?'hello')?
        'he',?'llo')?{}>

        若要在精準/模糊匹配的模式下,再進行格式轉換,可以這樣寫

        >>>?parse('{:2}{:2}',?'1024')?
        '10',?'24')?{}>
        >>>?
        >>>?
        >>>?parse('{:2d}{:2d}',?'1024')?
        10,?24)?{}>

        8. 三個重要屬性

        Parse 里有三個非常重要的屬性

        • fixed:利用位置提取的匿名字段的元組
        • named:存放有命名的字段的字典
        • spans:存放匹配到字段的位置

        下面這段代碼,帶你了解他們之間有什么不同

        >>>?profile?=?parse("I?am?{name},?{age:d}?years?old,?{}",?"I?am?Jack,?27?years?old,?male")
        >>>?profile.fixed
        ('male',)
        >>>?profile.named
        {'age':?27,?'name':?'Jack'}
        >>>?profile.spans
        {0:?(25,?29),?'age':?(11,?13),?'name':?(5,?9)}
        >>>?

        9. 自定義類型的轉換

        匹配到的字符串,會做為參數(shù)傳入對應的函數(shù)

        比如我們之前講過的,將字符串轉整型

        >>>?parse("I?am?{:d}",?"I?am?27")
        27,)?{}>
        >>>?type(_[0])
        'int'>
        >>>?

        其等價于

        >>>?def?myint(string):
        ...?????return?int(string)
        ...?
        >>>?
        >>>?
        >>>?parse("I?am?{:myint}",?"I?am?27",?dict(myint=myint))
        27,)?{}>
        >>>?type(_[0])
        'int'>
        >>>

        利用它,我們可以定制很多的功能,比如我想把匹配的字符串弄成全大寫

        >>>?def?shouty(string):
        ...????return?string.upper()
        ...
        >>>?parse('{:shouty}?world',?'hello?world',?dict(shouty=shouty))
        'HELLO',)?{}>
        >>>

        10 總結一下

        parse 庫在字符串解析處理場景中提供的便利,肉眼可見,上手簡單。

        在一些簡單的場景中,使用 parse 可比使用 re 去寫正則開發(fā)效率不知道高幾個 level,用它寫出來的代碼富有美感,可讀性高,后期維護起代碼來一點壓力也沒有,推薦你使用。

        戀習Python

        關注戀習Python,Python都好練


        好文章,我在看??
        瀏覽 25
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            色色色香蕉 | 五月丁香欧美综合亚洲 | 亚洲在线播放 | 欧美女人的b | 国产清纯白嫩初高生在线 | 中文字幕亚洲有码 | 亚洲国产图 | 操xxx | 逼逼插| 国产一級A片免费看 |