歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> 關於Unix

流行的腳本語言Python中的文本處理

什麼是 Python? Python 是由 Guido van Rossum 開發 的、可免費獲得的、非常高級的解釋型語言。其語法簡單易懂,而其 面向對象 的語義功能強大(但又靈活)。Python 可以廣泛使用並具有高度的可移植性。 字符串 -- 不可改變的序列 如同大多數高級編程語言一
  什麼是 Python?
  Python 是由 Guido van Rossum 開發的、可免費獲得的、非常高級的解釋型語言。其語法簡單易懂,而其面向對象的語義功能強大(但又靈活)。Python 可以廣泛使用並具有高度的可移植性。
  
  字符串 -- 不可改變的序列
  如同大多數高級編程語言一樣,變長字符串是 Python 中的基本類型。Python 在“後台”分配內存以保存字符串(或其它值),程序員不必為此操心。Python 還有一些其它高級語言沒有的字符串處理功能。
  
  在 Python 中,字符串是“不可改變的序列”。盡管不能“按位置”修改字符串(如字節組),但程序可以引用字符串的元素或子序列,就象使用任何序列一樣。Python 使用靈活的“分片”操作來引用子序列,字符片段的格式類似於電子表格中一定范圍的行或列。以下交互式會話說明了字符串和字符片段的的用法:
  
  字符串和分片
  >>> s = "mary had a little lamb"
  >>> s[0] # index is zero-based
  'm'
  >>> s[3] = 'x' # changing element in-place fails
  Traceback (innermost last):
   File "<stdin>", line 1, in ?
  TypeError: object doesn't support item assignment
  >>> s[11:18] # 'slice' a subsequence
  'little '
  >>> s[:4] # empty slice-begin assumes zero
  'mary'
  >>> s[4] # index 4 is not included in slice [:4]
  ' '
  >>> s[5:-5] # can use "from end" index with negatives
  'had a little'
  >>> s[:5]+s[5:] # slice-begin & slice-end are complimentary
  'mary had a little lamb'
  
  另一個功能強大的字符串操作就是簡單的 in 關鍵字。它提供了兩個直觀有效的構造:
  
  in 關鍵字
  >>> s = "mary had a little lamb"
  >>> for c in s[11:18]: print c, # print each char in slice
  ...
  l i t t l e
  >>> if 'x' in s: print 'got x' # test for char oclearcase/" target="_blank" >ccurrence
  ...
  >>> if 'y' in s: print 'got y' # test for char occurrence
  ...
  got y
  
  在 Python 中,有幾種方法可以構成字符串文字。可以使用單引號或雙引號,只要左引號和右引號匹配,常用的還有其它引號的變化形式。如果字符串包含換行符或嵌入引號,三重引號可以很方便地定義這樣的字符串,如下例所示:
  
  三重引號的使用
  >>> s2 = """Mary had a little lamb
  ... its fleece was white as snow
  ... and everywhere that Mary went
  ... the lamb was sure to go"""
  >>> print s2
  Mary had a little lamb
  its fleece was white as snow
  and everywhere that Mary went
  the lamb was sure to go
  
  使用單引號或三重引號的字符串前面可以加一個字母 "r" 以表示 Python 不應該解釋規則表達式特殊字符。例如:
  
  使用 "r-strings"
  
  >>> s3 = "this and that"
  >>> print s3
  this
  and
  that
  >>> s4 = r"this and that"
  >>> print s4
  this and that
  
  在 "r-strings" 中,可能另外組成換碼符的反斜槓被當作是常規反斜槓。在以後的規則表達式討論中會進一步說明這個話題。
  
  文件和字符串變量
  我們談到“文本處理”時,我們通常是指處理的內容。Python 將文本文件的內容讀入可以操作的字符串變量非常容易。文件對象提供了三個“讀”方法: .read()、.readline() 和 .readlines()。每種方法可以接受一個變量以限制每次讀取的數據量,但它們通常不使用變量。 .read() 每次讀取整個文件,它通常用於將文件內容放到一個字符串變量中。然而 .read() 生成文件內容最直接的字符串表示,但對於連續的面向行的處理,它卻是不必要的,並且如果文件大於可用內存,則不可能實現這種處理。
  
  .readline() 和 .readlines() 非常相似。它們都在類似於以下的結構中使用:
  
  Python .readlines() 示例
  
      fh = open('c:\autoexec.bat')
  for line in fh.readlines():
   print line
  
  .readline() 和 .readlines() 之間的差異是後者一次讀取整個文件,象 .read() 一樣。.readlines() 自動將文件內容分析成一個行的列表,該列表可以由 Python 的 for ... in ... 結構進行處理。另一方面,.readline() 每次只讀取一行,通常比 .readlines() 慢得多。僅當沒有足夠內存可以一次讀取整個文件時,才應該使用 .readline()。
  
  如果正在使用處理文件的標准模塊,可以使用 cStringIO 模塊將字符串轉換成“虛擬文件”(如果需要生成模塊的子類,可以使用 StringIO 模塊,初學者未必要這樣做)。例如:
  
  cStringIO 模塊
  >>> import cStringIO
  >>> fh = cStringIO.StringIO()
  >>> fh.write("mary had a little lamb")
  >>> fh.getvalue()
  'mary had a little lamb'
  >>> fh.seek(5)
  >>> fh.write('ATE')
  >>> fh.getvalue()
  'mary ATE a little lamb'
  
  但是,請記住,cStringIO“虛擬文件”不是永久的,這一點與真正的文件不同。如果不保存它(如將它寫入一個真正的文件,或者使用 shelve 模塊或數據庫),則程序結束時,它將消失。
  
  標准模塊:string
  string 模塊也許是 Python 1.5.* 標准發行版中最常用的模塊。實際上,在 Python 1.6 或更高版本中,string 模塊中的功能將作為內置字符串方法(在撰寫本文時,詳細信息尚未發布)。當然,任何執行文本處理任務的程序也許應該用以下這行開頭:
  
  開始使用 string 的方法
  
     import string
  
  一般經驗法則告訴我們,如果可以使用 string 模塊完成任務,那麼那就是正確的方法。與 re(規則表達式)相比,string 函數通常更快速,大多數情況下他們更易於理解和維護。第三方 Python 模塊,包括某些用 C 編寫的快速模塊,適用於專門的任務,但可移植性和熟悉性都建議只要可能就使用 string。如果您習慣於使用其它語言,也會有例外,但不如您想像的那樣多。
  
  string 模塊包含了幾種類型的事物,如函數、方法和類;它還包含了公共常量的字符串。例如:
  
  string 用法例 1
  >>> import string
  >>> string.whitespace
  '1112131415 '
  >>> string.uppercase
  'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  
  雖然可以用手寫出這些常量,string 版本或多或少確保了常量對於運行 Python 腳本的國家語言和平台將是正確的。
  
  string 還包括了以常見方式(可以結合這些方式來構成幾種罕見的轉換)轉換字符串的函數。例如:
  
  string 用法例 2
  >>> import string
  >>> s = "mary had a little lamb"
  >>> string.capwords(s)
  'Mary Had A Little Lamb'
  >>> string.replace(s, 'little', 'ferocious')
  'mary had a ferocious lamb'
  
  還有許多沒有在這裡具體說明的其它轉換;可以在 Python 手冊中查找詳細信息。
  
  還可以使用 string 函數來報告字符串屬性,如子串的長度或位置,例如:
  
  string 用法例 3
  >>> import string
  >>> s = "mary had a little lamb"
  >>> string.find(s, 'had')5>>> string.count(s, 'a')4
  
  最後,string 提供了非常 Python 化的奇特事物。.split() 和 .join() 對提供了在字符串和字節組之間轉換的迅捷方法,您會發現它們非常有用。用法很簡單:
  
  string 用法例 4
  >>> import string>>> s = "mary had a little lamb"
  >>> L = string.split(s)
  >>> L
  ['mary', 'had', 'a', 'little', 'lamb']
  >>> string.join(L, "-")
  'mary-had-a-little-lamb'
  
  當然,除了 .join() 之外,也許會利用列表來做其它事(如某些涉及我們熟悉的 for ... in ... 結構的事情)。
  
  標准模塊:re
  re 模塊廢棄了在老的 Python 代碼中使用的 regex 和 regsub 模塊。雖然相對於 regex 仍然有幾個有限的優點,不過這些優點微不足道,不值得在新代碼中使用。過時的模塊可能會從未來的 Python 發行版中刪除,並且 1.6 版可能有一個改進的接口兼容的 re 模塊。所以,規則表達式仍將使用 re 模塊。
  
  規則表達式很復雜。也許有人會撰寫關於這個主題的書,但實際上,已經有許多人這樣做了!本文嘗試捕捉規則表達式的“完全形態”,讓讀者可以掌握它。
  
  規則表達式是一種很簡練方法,用於描述可能在文本中出現的模式。是否會出現某些字符?是否按特定順序出現?子模式是否會重復一定次數?其它子模式是否會排除在匹配之外?從概念上說,似乎不能用自然語言了直觀地描述模式。訣竅是使用規則表達式的簡潔語法來編碼這種描述。
  
  當處理規則表達式時,將它作為它自己的編程問題來處理,即使只涉及一或兩行代碼;這些行有效地構成了一個小程序。
  
  從最小處著手。從最基本上看,任何規則表達式都涉及匹配特定的“字符類”。最簡單的字符類就是單個字符,它在模式中只是一個字。通常,您希望匹配一類字符。可以通過將類括在方括號內來表明這是一個類;在括號中,可以有一組字符或者用破折號指定的字符范圍。還可以使用許多命名字符類來確定您的平台和國家語言。以下是一些示例:
  
  字符類
  >>> import re
  >>> s = "mary had a little lamb"
  >>> if re.search("m", s): print "Match!" # char literal
  Match!
  >>> if re.search("[@A-Z]", s): print "Match!" # char class
  ... # match either at-sign or capital letter
  ...
  >>> if re.search("d", s): print "Match!" # digits class
  ...
  
  可以將字符類看作是規則表達式的“原子”,通常會將那些原子組合成“分子”。可以結合使用 分組和循環來完成此操作。由括號表示分組:括號中包含的任何子表達式都被看作是用於以後分組或循環的原子。循環則由以下幾個運算符中的某一個來表示:"*" 表示“零或多”;"+" 表示“一或多”;"?" 表示“零或一”。例如,請看以下示例:
  
  樣本規則表達式
  
  ABC([d-w]*dd?)+XYZ
  
  對於要匹配這個表達式的字符串,它必須以 "ABC" 開頭、以 "XYZ" 結尾 -- 但它的中間必須要有什麼呢?中間子表達式是 ([d-w]*dd?),而且後面跟了“一或多”運算符。所以,字符串的中間必須包括一個(或者兩個,或者一千個)與括號中的子表達式匹配的字符或字符串。字符串 "ABCXYZ" 不匹配,因為它的中間沒有必要的字符。
  
  不過這個內部子表達式是什麼呢?它以 d-w 范圍內的零或多個字母開頭。一定要注意:零字母是有效匹配,雖然使用英語單詞 "some"(一些)來描述它,可能會感到很別扭。接著,字符串必須恰好有一個數字;然後有 零或一個附加數字。(第一個數字字符類沒有循環運算符,所以它只出現一次。第二個數字字符類有 "?" 運算符。)總而言之,這將翻譯成“一個或兩個數字”。以下是一些與規則表達式匹配的字符串:
  
  匹配樣本表達式的字符串
  
  ABC1234567890XYZ
  ABCd12e1f37g3XYZ
  ABC1XYZ
  
  還有一些表達式與規則表達式不匹配(想一想,它們為什麼不匹配):
  
  不匹配樣本表達式的字符串
  
  ABC123456789dXYZ
  ABCdefghijklmnopqrstuvwXYZ
  ABcd12e1f37g3XYZ
  ABC12345%67890XYZ
  ABCD12E1F37G3XYZ
  
  需要一些練習才能習慣創建和理解規則表達式。但是,一旦掌握了規則表達式,您就具有了強大的表達能力。也就是說,轉而使用規則表達式解決問題通常會很容易,而這類問題實際上可以使用更簡單(而且更快速)的工具,如 string,來解決。

Copyright © Linux教程網 All Rights Reserved