與 Perl 和 Python 類似,Ruby 擁有出色的功能,是一種強大的文本處理語言。本文簡單介紹了 Ruby 的文本數據處理功能,以及如何使用 Ruby 語言有效處理不同格式的文本數據,無論是 CSV 數據還是 XML 數據。
Ruby 字符串
常用縮略詞
Ruby 中的 String 是容納、比較和操作文本數據的一種強大方法。在 Ruby 中,String 是一個類,可以通過調用 String::new 或向它分配一個字面值將它實例化。
向 Strings 賦值時,可以使用單引號(')或雙引號(")來包圍值。單引號和雙引號在為 Strings 賦值時有幾個差別。雙引號支持轉義序列使用一個前置反斜杠(/)并支持在字符串中使用 #{} 操作符計算表達式。而單引號引用的字符串則是簡單直接的文字。
清單 1 是一個示例。
清單 1. 處理 Ruby 字符串:定義字符串
message = 'Heal the World…'puts messagemessage1 = "Take home Rs #{100*3/2} "puts message1Output :# ./string1.rb# Heal the World…# Take home Rs 150
這里,第一個字符串使用一對單引號定義,第二個字符串使用一對雙引號定義。在第二個字符串中,#{} 中的表達式在顯示前計算。
另一種有用的字符串定義方法通常用于多行字符串定義。
從現在開始,我將使用交互式 Ruby 控制臺 irb>> 進行說明。您的 Ruby 安裝也應該安裝該控制臺。如果沒有安裝,建議您獲取 irb Ruby gem 并安裝它。Ruby 控制臺是學習 Ruby 及其模塊的一個非常有用的工具。安裝之后,可以使用 irb>> 命令運行它。
清單 2. 處理 Ruby 字符串:定義多個字符串
irb>> str = >>EOFirb>> "hello worldirb>> "how do you feel?irb>> "how r u ?irb>> EOF"hello, world/nhow do you feel?/nhow r u?/n"irb>> puts strhello, worldhow do you feel?how r u?
在 清單 2 中,>>EOF 和 EOF 中的所有內容都視為字符串的一部分,包括 /n(換行)字符。
Ruby String 類有一組強大的方法用于操作和處理存儲在它們之中的數據。清單 3、4 和 5 中的示例展示了部分方法。
清單 3. 處理 Ruby 字符串:連接字符串
irb>> str = "The world for a horse" # String initialized with a valueThe world for a horseirb>> str*2 # Multiplying with an integer returns a # new string containing that many times # of the old string.The world for a horseThe world for a horseirb>> str + " Who said it ? " # Concatenation of strings using the '+' operatorThe world for a horse Who said it ?irb>> str<<" is it? " # Concatenation using the '<<' operatorThe world for a horse is it?
提取子字符串并操作字符串的多個部分
清單 4. 處理 Ruby 字符串:提取并操作
irb>> str[0] # The '[]' operator can be used to extract substrings, just # like accessing entries in an array. # The index starts from 0.84 # A single index returns the ascii value # of the character at that positionirb>> str[0,5] # a range can be specified as a pair. The first is the starting # index , second is the length of the substring from the # starting index.The wirb>> str[16,5]="Ferrari" # The same '[]' operator can be used # to replace substrings in a string # by using the assignment like '[]='irb>>strThe world for a FerrariIrb>> str[10..22] # The range can also be specified using [x1..x2] for a Ferrariirb>> str[" Ferrari"]=" horse" # A substring can be specified to be replaced by a new # string. Ruby strings are intelligent enough to adjust the # size of the string to make up for the replacement string.irb>> sThe world for a horseirb>> s.split # Split, splits the string based on the given delimiter # default is a whitespace, returning an array of strings.["The", "world", "for", "a", "horse"]irb>> s.each(' ') { |str| p str.chomp(' ') } # each , is a way of block processing the # string splitting it on a record separator # Here, I use chomp() to cut off the trailing space"The""world""for""a""horse"
Ruby String 類還可以使用許多其他實用方法,這些方法可以更改大小寫、獲取字符串長度、刪除記錄分隔符、掃描字符串、加密、解密等。另一個有用的方法是 freeze,該方法可以使字符串變得不可修改。對 String str 調用該方法(str.freeze)之后,str 將不能被修改。
Ruby 還有一些稱為 “析構器(destructor)” 的方法。以感嘆號(!)結尾的方法將永久修改字符串。常規方法(結尾沒有感嘆號)修改并返回調用它們的字符串的副本。而帶有感嘆號的方法直接修改調用它們的字符串。
清單 5. 處理 Ruby 字符串:永久修改字符串
irb>> str = "hello, world"hello, worldirb>> str.upcaseHELLO, WORLDirb>>str # str, remains as is.Hello, worldirb>> str.upcase! # here, str gets modified by the '!' at the end of # upcase.HELLO, WORLDirb>> strHELLO, WORLD
在 清單 5 中,str 中的字符串由 upcase! 方法修改,但 upcase 方法只返回大小寫修改后的字符串副本。這些 ! 方法有時很有用。
Ruby Strings 的功能非常強大。數據被捕獲進 Strings 中后,您就能夠任意使用多種方法輕松有效地處理這些數據。
處理 CSV 文件
CSV 文件是表示表格式的數據的一種很常見的方法,表格式通常用作從電子表格導出的數據(比如帶有詳細信息的聯系人列表)的格式。
Ruby 有一個強大的庫,可以用于處理這些文件。csv 是負責處理 CSV 文件的 Ruby 模塊,它擁有創建、讀取和解析 CSV 文件的方法。
清單 6 展示了如何創建一個 CSV 文件并使用 Ruby csv 模塊來解析文件。
清單 6. 處理 CSV 文件:創建并解析一個 CSV 文件
require 'csv'writer = CSV.open('mycsvfile.csv','w')begin print "Enter Contact Name: " name = STDIN.gets.chomp print "Enter Contact No: " num = STDIN.gets.chomp s = name+" "+num row1 = s.split writer << row1 print "Do you want to add more ? (y/n): " ans = STDIN.gets.chompend while ans != "n"writer.closefile = File.new('mycsvfile.csv')lines = file.readlinesparsed = CSV.parse(lines.to_s)p parsedputs ""puts "Details of Contacts stored are as follows..."puts ""puts "-------------------------------"puts "Contact Name | Contact No"puts "-------------------------------"puts ""CSV.open('mycsvfile.csv','r') do |row| puts row[0] + " | " + row[1] puts ""end
清單 7 顯示了輸出:
清單 7. 處理 CSV 文件:創建并解析一個 CSV 文件輸出
Enter Contact Name: SanthoshEnter Contact No: 989898Do you want to add more ? (y/n): yEnter Contact Name: SandyEnter Contact No: 98988Do you want to add more ? (y/n): nDetails of Contacts stored are as follows...---------------------------------Contact Name | Contact No---------------------------------Santhosh | 989898Sandy | 98988
讓我們快速檢查一下這個示例。
首先,包含 csv 模塊(require 'csv')。
要創建一個新的 CSV 文件 mycsvfile.csv,使用 CSV.open() 調用打開它。這返回一個寫入器(writer)對象。
這個示例創建了一個 CSV 文件,該文件包含一個簡單的聯系人列表,存儲聯系人姓名及其電話號碼。在循環中,用戶被要求輸入聯系人姓名和電話號碼。姓名和電話號碼被連接為一個字符串,然后分割為含兩個字符串的數組。這個數組傳遞到寫入器對象以便寫入 CSV 文件。這樣,一對 CSV 值就存儲為文件中的一行。
循環結束后,任務也就完成了。現在關閉寫入器,文件中的數據得以保存。
下一步是解析創建的 CSV 文件。
打開和解析該文件的一種方法是使用新的 CSV 文件名稱創建一個新的 File 對象。
調用 readlines 方法將文件中的所有行讀入一個名為 lines 的數組。
通過調用 lines.to_s 將 lines 數組轉換為一個 String 對象,然后將這個 String 對象傳遞到 CSV.parse 方法,該方法解析 CSV 數據并將其內容返回為一個包含數組的數組。
下面介紹打開和解析該文件的另一種方法。以讀取模式使用 CSV.open 調用再次打開文件。這返回一個行數組。使用某種格式打印每個行以顯示聯系人細節。這里的每個行對應文件中的行。
如您所見,Ruby 提供一個強大的模塊來處理 CSV 文件和數據。
處理 XML 文件
對于 XML 文件,Ruby 提供一個名為 REXML 的強大的內置庫。這個庫可以用于讀取和解析 XML 文檔。
查看以下 XML 文件并試圖用 Ruby 和 REXML 來解析它。
下面是一個簡單的 XML 文件,列示一個在線購物中心的典型購物車中的內容。它擁有以下元素:
清單 8 展示了這個 XML 的結構:
清單 8. 處理 XML 文件:示例 XML 文件
<cart id="userid"><item code="item-id"> <price> <price/unit> </price> <qty> <number-of-units> </qty></item></cart>
從 下載 部分獲取這個示例 XML 文件。現在,加載這個 XML 文件并使用 REXML 解析文件樹。
清單 9. 處理 XML 文件:解析 XML 文件
require 'rexml/document'include REXMLfile = File.new('shoppingcart.xml')doc = Document.new(file)root = doc.rootputs ""puts "Hello, #{root.attributes['id']}, Find below the bill generated for your purchase..."puts ""sumtotal = 0puts "-----------------------------------------------------------------------"puts "Item/t/tQuantity/t/tPrice/unit/t/tTotal"puts "-----------------------------------------------------------------------"root.each_element('//item') { |item| code = item.attributes['code']qty = item.elements["qty"].text.split(' ')price = item.elements["price"].text.split(' ')total = item.elements["price"].text.to_i * item.elements["qty"].text.to_iputs "#[code]/t/t #{qty}/t/t #{price}/t/t #{total}"puts ""sumtotal += total}puts "-----------------------------------------------------------------------"puts "/t/t/t/t/t/t Sum total : " + sumtotal.to_sputs "-----------------------------------------------------------------------"
清單 10 顯示輸出。
清單 10. 處理 XML 文件:解析 XML 文件輸出
Hello, santhosh, Find below the bill generated for your purchase...-------------------------------------------------------------------------Item Quantity Price/unit Total-------------------------------------------------------------------------CS001 2 100 200CS002 5 200 1000CS003 3 500 1500CS004 5 150 750------------------------------------------------------------------------- Sum total : 3450--------------------------------------------------------------------------
清單 9 解析這個購物車 XML 文件并生成一個賬單,該賬單顯示項目合計和采購總計(見 清單 10)。
下面我們具體介紹操作過程。
首先,包含 Ruby 的 REXML 模塊,該模塊擁有解析 XML 文件的方法。
打開 shoppingcart.xml 文件并從該文件創建一個 Document 對象,該對象包含解析后的 XML 文件。
將文檔的根分配給元素對象 root。這將指向 XML 文件中的 cart 標記。
每個元素對象擁有一個屬性對象,該屬性對象是元素屬性的 hash 表,其中屬性名稱作為鍵名,屬性值作為鍵值。這里,root.attributes['id'] 將提供 root 元素的 id 屬性的值(本例中為 userid)。
下面,將 sumtotals 初始化為 0 并打印標頭。
每個元素對象還有一個對象 elements,該對象擁有 each 和 [] 方法,以便訪問子元素。這個對象遍歷所有帶有 item 名稱(通過 XPath 表達式 //item 指定)的 root 元素的子元素。每個元素還有一個屬性 text,該屬性容納元素的文本值。
下一步,獲取 item 元素的 code 屬性以及 price 和 qty 元素的文本值,然后計算項目合計(Total)。將詳細信息打印到賬單并將項目合計添加到采購總計(Sum total)。
最后,打印采購總計。
這個示例展示了使用 REXML 和 Ruby 解析 XML 文件有多么簡單!同樣,在運行中生成 XML 文件,添加和刪除元素及它們的屬性也很簡單。
清單 11. 處理 XML 文件:生成 XML 文件
doc = Document.newdoc.add_element("cart1", {"id" => "user2"})cart = doc.root.elements[1]item = Element.new("item")item.add_element("price")item.elements["price"].text = "100"item.add_element("qty")item.elements["qty"].text = "4"cart .elements << item
清單 11 中的代碼通過創建一個 cart 元素、一個 item 元素和它的子元素來創建 XML 結構,然后使用值填充這些子元素并將它們添加到 Document 根。
類似地,要刪除元素和屬性,使用 Elements 對象的 delete_element 和 delete_attribute 方法。
以上示例中的方法稱為樹解析(tree parsing)。另一種 XML 文檔解析方法稱為流解析(stream parsing)。“流解析” 比 “樹解析” 更快,可以用于要求快速解析的情況。“流解析” 是基于事件的,它使用監聽器。當解析流遇到一個標記時,它將調用監聽器并執行處理。
清單 12 展示了一個示例:
清單 12. 處理 XML 文件:流解析
require 'rexml/document'require 'rexml/streamlistener'include REXMLclass Listener include StreamListener def tag_start(name, attributes) puts "Start #{name}" end def tag_end(name) puts "End #{name}" endendlistener = Listener.newparser = Parsers::StreamParser.new(File.new("shoppingcart.xml"), listener)parser.parse
清單 13 顯示輸出:
清單 13. 處理 XML 文件:流解析輸出
Start cartStart itemStart priceEnd priceStart qtyEnd qtyEnd itemStart itemStart priceEnd priceStart qtyEnd qtyEnd itemStart itemStart priceEnd priceStart qtyEnd qtyEnd itemStart itemStart priceEnd priceStart qtyEnd qtyEnd itemEnd cart
這樣,REXML 和 Ruby 聯合起來為您提供一種非常有效和直觀地處理和操作 XML 數據的強大方法。
結束語
Ruby 擁有一組很好的內置庫和外部庫,支持快速、強大和有效的文本處理。您可以利用該功能簡化和改進可能遇到的各種文本數據處理工作。本文只是 Ruby 的文本處理功能的簡要介紹,您可以進一步深入了解該功能。
毋庸置疑,Ruby 是您需要的一個強大工具。
新聞熱點
疑難解答
圖片精選