iT邦幫忙

0

[Python]B13─字串處理(string processing)

Hi! 大家好,我是Eric,這次教大家Python的字串處理(string processing)!
/images/emoticon/emoticon07.gif

■ 字串處理(string processing)

■ 定義字串

x = "abc"         # 可用雙引號定義
x = 'abc'         # 也可用單引號定義
x = """           # 可用三重引號跨行定義字串
abc
xyz
"""

■ 簡易字串操作

  • 產生字串
pi=3.14
     
str(pi)
"The value of pi is " + str(pi)
  • 字串格式化:大小寫轉換
fox = "bHkloY"
fox.upper()      #全部字元轉成大寫
fox.lower()      #全部字元轉成小寫
fox.title()      #首字轉成大寫
fox.capitalize   #每個字詞的首字轉成大寫
fox.swapacase    #將大小寫顛倒
  • 字串格式化:新增和刪除空格
line="      adf     "  
line.strip()       #刪除前後的空格
line.rstrip()      #刪除右邊的空格
line.lstrip()      #刪除左邊的空格
     
num="00000345"
num.strip("0")     #刪除特定字元
     
line = "this is the content"
line.center(30)      #產生一定數量的空格,並中心對齊一個給定的字串
line.ljust(30)       #產生一定長度的空格並左對齊
line.rjust(30)       #產生一定長度的空格並右對齊
"345".rjust(10,"0")  #能以任意字元填充空格
"345".zfill(10)      #在左邊填充一定數量的0
  • 查詢和替換⼦字串
line = 'the quick brown fox jumped over a lazy dog'
line.find('fox')      #查詢子字串在字串中出現的索引,若搜尋不到子字串,會回傳-1
line.index('fox')     #查詢子字串在字串中出現的索引,若搜尋不到子字串,會回傳ValueError
line.rfind('fox')     #從尾部往前查詢子字串在字串中出現的索引
    
line.endswith('dog')         #檢查字串尾部的子字串
linie.startswith('fox')      #檢查字串頭部的子字串
    
line.replace('brown','red')  #以第2個參數替換子字串
  • 拆分和分割字串
line.partition('fox')
#partition()會回傳3個tuple,分別是:目標子字串之前的子字串、目標子字串、目標子字串之後的子字串
line.rpartition('fox') #rpartition()從右向左搜尋字串
line.split()           #split()預設以空白作為分割依據,回傳所有單字
       
haiku = """matsushima-ya
aah matsushima-ya
matsushima-ya"""
   
haiku.splitlines()      #splitlines()對換行符號進行分割
        
'--'.join(['1', '2', '3'])   #撤銷split()的結果,用分割依據再組成一個字串
print("\n".join(['matsushima-ya', 'aah matsushima-ya',    #常見的用法是用換行符號還原成原字串
'matsushima-ya']))

■ 格式化字串

  • 格式化字串
pi=3.14
"The value of pi is {}".format(pi)      #以{}代表將要插入字串格式化後的值
"""First letter: {0}. Last letter: {1}.""" .format('A', 'Z')
#{}中設定數字代表要插入的參數的索引
"""First letter: {first}. Last letter: {last}.""" .format(last='Z', first='A')
#若{}中包括了一個字串,則可以名稱指定要插入的值
"pi = {0:.3f}".format(pi)
#數字的插入,0代表要插入的參數的索引,:代表後面要跟著格式化的程式碼,.3f代表需要的精度資訊,小數點後保留3位小數的浮點數

■ 使用正則表達式靈活地匹配字串模式

  • 正則表達式。Python ⽀援正則表達式的介⾯存放在內建的 re 模組中
line = 'the quick brown fox jumped over a lazy dog'
  • 正則表達式的spilt()
    我們編譯一個正則表達式,然後用它來分割字符串,和Python的spilt()一樣,返回了一個包含所有空格之間的子字 串的列表。
import re
regex = re.compile('\s+')    
regex.split(line) 
#\s是一個特殊的字元,匹配所有空白字元(包含空格、TAB字元、換行符號等),+指名它在實體出現一次或多次。
  • 正則表達式的match(),會回傳一個字串的開頭是否匹配了模式串
for s in [" ", "abc ", " abc"]:
     if regex.match(s):
         print(repr(s), "matches")
     else:
         print(repr(s), "does not match")
  • 正則表示式的regex.search(),類似str.index()、str.find(),會搜尋子字串在字串中的索引
line = 'the quick brown fox jumped over a lazy dog'
regex = re.compile('fox')
match = regex.search(line)
match.start()
  • 正則表達式的regex.sub(),類似str.replace(),會以第1個參數替換子字串
regex.sub('BEAR', line)

■ 一個更複雜的例子
既然使用原本的方法不是更為直覺更簡單嗎?為什麼要用比較複雜的正則表達式呢?因為正則表達式的優點不只是靈活性高而已。我們來想「匹配電子郵件地址」的問題吧,這邊示範的只是簡單的例子,無法用於實作上

  • 如果有一行文字,可用正則表達式快速取得像是電子郵件地址的內容
text = "To email Guido, try guido@python.org or the older address "\
         "guido@google.com."
email = re.compile('\w+@\w+\.[a-z]{3}')
email.findall(text)

#我們可以進行進一步的操作,像是把電子郵件地址換成其他的字元串,達到保護個資的作用
email.sub('--@--.--', text)
  • 正則表達式的語法基礎

  • 簡單的字串直接匹配

regex = re.compile('ion')
regex.findall('Great Expectations')
  • 有一些字元在正則表達式中是有特殊意義的,使用上需要用反斜線()跳脫他們,所以在正則表達式中
. ^ $ * + ? { } [ ] \ | ( )
       
regex = re.compile(r'\$')      #r表明是一個原始字串(raw string),\代表特殊的字元
regex.findall("the cost is $20")  
       
print('a\tb\tc')     #\t是代表tab作用  
print(r'a\tb\tc')    #在原始字串中不會作用
字元 描述
d 匹配任意數字
D 匹配任意非數字
s 匹配任意空⽩字元
S 匹配任意非空⽩字元
w 匹配任意字⺟和數字
W 匹配任意非字⺟和數字
  • 除了內建特殊字元外,我們也可以自定義字元。如下自定義小寫母音字母
regex = re.compile('[aeiou]')
regex.split('consequential')
  • 可以短橫線(-)指定字符範圍,如[a-z]匹配任意小寫字母,[1-3]匹配任意數字1、2、3
regex = re.compile('[A-Z][0-9]')
regex.findall('1043879, G2, H6')
  • 若想要匹配三個字母或三個數字的字串,一般可用\w\w\w,但更具體的語法可用{數字}
regex = re.compile(r'\w{3}')
regex.findall('The quick brown fox')
  • 另外,也可使用一些標記來匹配任意數量的重複字符,如+會匹配前面字元出現1或多次重複的情形
regex = re.compile(r'\w+')
regex.findall('The quick brown fox')
  • 下面整理了一些正則表達式重要標記(字元為用''括起來的符號,如第一行字元為?)
字元 描述 舉例
'?' 匹配前面字元 0 次或 1 次重複 ab?匹配 "a" 或 "ab"
'*' 匹配前面字元 0 次或多次重複 ab星號匹配 "a"、"ab"、"abb"、"abbb"等等
'+' 匹配前面字元 1 次或多次重複 ab+匹配 "ab"、"abb"、"abbb"等等,但是不匹配 "a"
'{n}' 匹配前面字元 n 次重複 ab{2}匹配 "abb"
'{m,n}' 匹配前面字元 m 次到 n 次重複 ab{2,3}匹配 "abb" 或 "abbb"
  • 我們回到之前電子郵件地址匹配的正則表達式,現在可以理解下列的意思:我們需要⼀個或者多個數字或字母(\w+) 後跟 at 符號(@),然後接⼀個或者多個數字或字母(\w+),跟著⼀個句號(.,注意這裡需要⼀個反斜槓轉 義),最後跟恰好三個⼩寫字母([a-z]{3})。
email = re.compile(r'\w+@\w+\.[a-z]{3}')
  • 接著,我們使用[],就能夠匹配任意字母或數字或句號
email2 = re.compile(r'[\w.]+@\w+\.[a-z]{3}')
email2.findall('barack.obama@whitehouse.gov')
  • 我們可再加上()進行分組提取
email3 = re.compile(r'([\w.]+)@(\w+)\.([a-z]{3})')
text = "To email Guido, try guido@python.org or the older address "\
"guido@google.com."
email3.findall(text)
  • 可再進一步使用?P給提取的組命名
email4 = re.compile(r'(?P<user>[\w.]+)@(?P<domain>\w+)'\
                       '.(?P<suffix>[a-z]{3})')
match = email4.match('guido@python.org')
match.groupdict()

■ Refer to《Python 旋風之旅,[正體中文]Will保哥》的第15章


尚未有邦友留言

立即登入留言