1. 程式人生 > >Python核心程式設計第三版練習參考(第一章:正則表示式)

Python核心程式設計第三版練習參考(第一章:正則表示式)

1-1 識別後續的字串:“bat”、“bit”、“but”、“hat”、“hit”或者“hut”。

答:'[bh][aiu]t'


1-2 匹配由單個空格分隔的任意單詞對,也就是姓和名。

答:'\w+\s\w+'


1-3 匹配由單個逗號和單個空白符分隔的任何單詞和單個字母,如姓氏的首字母。

答:'\w+,\s\w+''

1-4 匹配所有有效Python識別符號的集合。

答:'[_A-Za-z]+[_\w]+'

1-5 根據讀者當地的格式,匹配街道地址(使你的正則表示式足夠通用,來匹配任意數量的街道單詞,包括型別名稱)。例如,美國街道地址使用如下格式:1180 Bordeaux Drive。使你的正則表示式足夠靈活,以支援多單詞的街道名稱,如3120 De la Cruz Boulevard。

答:r'\d+ .+'

1-6 匹配以“www”起始且以“.com”結尾的簡單Web域名;例如,www://www. yahoo.com/。選做題:你的正則表示式也可以支援其他高階域名,如.edu、.net等(例如,http://www.foothill.edu)。

答:(1)r'^www://.+.com$'

        (2)r'^www://.+.[com|edu|org|gov|net]$'

1-7 匹配所有能夠表示Python整數的字串集。

答:也就是說既可以表示正整數也可以表示正整數(我的個腦子啊,基本概念都不清了)

        r'[-\d]\d+'  #為了不輸出+,[]是從多箇中選一個(基礎還得練啊……)

1-8 匹配所有能夠表示Python長整數的字串集。

答:"\d+[1L]"

1-9 匹配所有能夠表示Python浮點數的字串集。

答:r'\d+(.\d*)'

1-10 匹配所有能夠表示Python複數的字串集。

答:r'\d+(\+\d*i)?'   #簡單的實部和虛部都是整數

        r'\d+(.\d*)((\+\d(.\d*))*i)?'         #搞得有些複雜,但是可以匹配實數的複數了,小夥伴誰有更簡潔的,可以共享啦^-^

1-11 匹配所有能夠表示有效電子郵件地址的集合(從一個寬鬆的正則表示式開始,然後嘗試使它儘可能嚴謹,不過要保持正確的功能)。

答:有效電子郵件地址

的規則:

        1.使用者名稱,可以自己選擇。由字母a~z(不區分大小寫)、數字0~9、點、減號或下劃線組成;只能以數字或字母開頭和結尾,例如:beijing.2008;使用者名稱長度為4~18個字元 。

         2.與你使用的網站有關,代表郵箱服務商。例如網易的有@163.com/@126.com/@188.com /@Yeah。com等;新浪的是@sina.com/@vip.sina.com等(也就還是字母數字組合)

         r'\w+(\.|\d|-|_)*\[email protected]\w+\.com'

1-12 匹配所有能夠表示有效的網站地址的集合(URL)(從一個寬鬆的正則表示式開始,然後嘗試使它儘可能嚴謹,不過要保持正確的功能)。

答:

1-13 type()。內建函式type()返回一個型別物件,如下所示,該物件將表示為一個Pythonic型別的字串。


    >>> type(0)  

    <type 'int'>

    >>> type(.34)  

    <type 'float'>

    >>> type(dir)  

    <type 'builtin_function_or_method'>


建立一個能夠從字串中提取實際型別名稱的正則表示式。函式將對類似於<type 'int' >的字串返回int(其他型別也是如此,如 'float' 、'builtin_function_or_method' 等)。注意:你所實現的值將存入類和一些內建型別的__name__屬性中。

答:r"type\s.(\w+)."

1-14 處理日期。1.2節提供了來匹配單個或者兩個數字字串的正則表示式模式,來表示1~9的月份(0?[1-9])。建立一個正則表示式來表示標準日曆中剩餘三個月的數字。

答:'(1[0-2])'

1-15 處理信用卡號碼。1.2節還提供了一個能夠匹配信用卡(CC)號碼([0-9]{15,16})的正則表示式模式。然而,該模式不允許使用連字元來分割數字塊。建立一個允許使用連字元的正則表示式,但是僅能用於正確的位置。例如,15位的信用卡號碼使用4-6-5的模式,表明4個數字-連字元-6個數字-連字元-5個數字;16位的信用卡號碼使用4-4-4-4的模式。記住,要對整個字串進行合適的分組。選做題:有一個判斷信用卡號碼是否有效的標準演算法。編寫一些程式碼,這些程式碼不但能夠識別具有正確格式的號碼,而且能夠識別有效的信用卡號碼。

答:(1)r'\d{4}-\d{4,6}-\d{4,5}(-\d{4})?'

        (2)def check(card):
    import re
    ma = re.search(r'\d{4}-(\d{4,6})-(\d{4,5})(-(\d{4}))?',"1234-123456-12345").group()
    if len(ma.group(1))==4:
        if len(ma.group(2))==4 and len(ma.group(4))==4:
            return True
        return False
    elif len(ma.group(1))==6:
        if len(ma.group(2)==5):
            return True
        return False
    else:
        return False

使用gendata.py。下面一組練習(1-16~1-27)專門處理由gendata.py生成的資料。在嘗試練習1-17和1-18之前,讀者需要先完成練習1-16以及所有正則表示式。

1-16 為gendata.py更新程式碼,使資料直接輸出到redata.txt而不是螢幕。

答:from random import randrange,choice
from string import ascii_lowercase as lc
from sys import maxint
from time import ctime
    
tlds = ('com','edu','net','org','gov')
f = open('redata.txt','a+')
for i in xrange(randrange(5,11)):
    dtint = randrange(maxint)
    dtstr = ctime(dtint)
    llen = randrange(4,8)
    login = ''.join(choice(lc) for j in range(llen))
    dlen = randrange(llen,13)
    dom = ''.join(choice(lc) for j in xrange(dlen))
    print '%s::%[email protected]%s.%s::%d-%d-%d' % (dtstr,login,dom,choice(tlds),dtint,llen,dlen)
    f.write('%s::%[email protected]%s.%s::%d-%d-%d\n' % (dtstr,login,dom,choice(tlds),dtint,llen,dlen))

1-17 判斷在redata.tex中一週的每一天出現的次數(換句話說,讀者也可以計算所選擇的年份中每個月中出現的次數)。

答:就是用模式串匹配月份

        r'\s\w{3}\s'

1-18 通過確認整數字段中的第一個整數匹配在每個輸出行起始部分的時間戳,確保在redata.txt中沒有資料損壞。
建立以下正則表示式。

答:

1-19 提取每行中完整的時間戳。

答:r'.{24}'     #偷懶了,因為完整時間戳就是24個任意字元

1-20 提取每行中完整的電子郵件地址。

答:re.search(r'::(\[email protected]\w+\.(com|net|cn|edu|gov))',"Fri Aug 06 02:32:59 2032::[email protected]::1975343579-5-7").group(1)

1-21 僅僅提取時間戳中的月份。

答:設定子組

1-22 僅僅提取時間戳中的年份。

答:設定子組


1-23 僅僅提取時間戳中的時間(HH:MM:SS)。

答:設定子組


1-24 僅僅從電子郵件地址中提取登入名和域名(包括主域名和高階域名一起提取)。

答:re.search(r'::(\w+)@(\w+)\.(?:com|net|cn|edu|gov)',"Fri Aug 06 02:32:59 2032::[email protected]::1975343579-5-7").groups()


1-25 僅僅從電子郵件地址中提取登入名和域名(包括主域名和高階域名)。

答:


1-26 使用你的電子郵件地址替換每一行資料中的電子郵件地址。

答:re.sub(r'::\[email protected]\w+\.(?:com|net|cn|edu|gov)','::[email protected]',"Fri Aug 06 02:32:59 2032::[email protected]::1975343579-5-7")


1-27 從時間戳中提取月、日和年,然後以“月,日,年”的格式,每一行僅僅迭代一次。

答:子組

處理電話號碼。

對於練習1-28和1-29,回顧1.2節介紹的正則表示式\d{3}-\d{3}-\d{4},它匹配電話號碼,但是允許可選的區號作為字首。更新正則表示式,使它滿足以下條件。
1-28 區號(三個整數集合中的第一部分和後面的連字元)是可選的,也就是說,正則表示式應當匹配800-555-1212,也能匹配555-1212。

答:re.match(r'(\d{3}-)?\d{3}-\d{4}','555-1212').group()


1-29 支援使用圓括號或者連字元連線的區號(更不用說是可選的內容);使正則表示式匹配800-555-1212、555-1212以及(800)555-1212。

答:re.match(r'((\d{3}-)|\(\d{3}\))?\d{3}-\d{4}','(800)555-1212').group()

正則表示式應用程式。下面練習在處理線上資料時生成了有用的應用程式指令碼。
1-30 生成HTML。提供一個連結列表(以及可選的簡短描述),無論使用者通過命令列方式提供、通過來自於其他指令碼的輸入,還是來自於資料庫,都生成一個Web頁面(.html),該頁面包含作為超文字錨點的所有連結,它可以在Web瀏覽器中檢視,允許使用者單擊這些連結,然後訪問相應的站點。如果提供了簡短的描述,就使用該描述作為超文字而不是URL。

答:


1-31 tweet精簡。有時候你想要檢視由Twitter使用者傳送到Twitter服務的tweet純文字。建立一個函式以獲取tweet和一個可選的“元”標記,該標記預設為False,然後返回一個已精簡過的tweet字串,即移除所有無關資訊,例如,表示轉推的RT符號、前導的“.”符號,以及所有#號標籤。如果元標記為True,就返回一個包含元資料的字典。這可以包含一個鍵“RT”,其相應的值是轉推該訊息的使用者的字串元組和/或一個鍵“#號標籤”(包含一個#號標籤元組)。如果值不存在(空元組),就不要為此建立一個鍵值條目。

答:


1-32 亞馬遜爬蟲指令碼。建立一個指令碼,幫助你追蹤你最喜歡的書,以及這些書在亞馬遜上的表現(或者能夠追蹤圖書排名的任何其他的線上書店)。例如,亞馬遜對於任何一本圖書提供以下連結:http://amazon.com/dp/ISBN(例如,http://amazon.com/ dp/0132678209)。讀者可以改變域名,檢查亞馬遜在其他國家的站點上相同的圖書排名,例如德國(.de)、法國(.fr)、日本(.jp)、中國(.cn)和英國(.co.uk)。使用正則表示式或者標記解析器,例如BeautifulSoup、lxml或者html5lib來解析排名,然後讓使用者傳入命令列引數,指明輸出是否應當在一個純文字中,也許包含在一個電子郵件正文中,還是用於Web的格式化HTML中。

答: