ruby: 嵌入字符串、% 呈現、ruby文件讀寫ruby way之IO之一

Ruby 入門: 嵌入字符串、% 呈現

嵌入字符串
在 Ruby 中我非常喜歡的一個功能就是嵌入字符串,所謂嵌入就是指直接將變量寫入引號的形式,這樣做的好處是直觀和節約了連字符出現的頻率。比如在 C# 中我們可以編寫下面的代碼。
string val = "value";
string printVal = "value: " + val;
// 或者
string printVal = String.Format("value: {0}", val);

但在 Ruby 中可以採用嵌入字符串的形式來節約一些代碼(我想這裏正體現了 Ruby 的優雅)。
val = "Value"
printVal 
= "value: #{val}"

嵌入字符串的形式是非常簡單的,只需將變量名放到 # 字符後面的大括號中就可以了。而對於類變量、成員變量和全局變量來說,甚至可以連大括號也可以省略掉(僞變量則不能省略大括號)。
 1module Company
 2  class Employee
 3    # 類變量
 4    @@companyName = ".org"
 5    # 成員變量
 6    @empId
 7    
 8    def setEmpId(val)
 9      @empId = val
10    end
11    
12    def display()
13      # 省略了大括號
14      print "Company: #@@companyName\n"
15      print "Employee ID: #@empId\n"
16      # 僞變量不能省略大括號
17      print "lines: #{__LINE__}\n"
18    end
19  end
20end
21
22emp = Company::Employee.new
23emp.setEmpId("001")
24emp.display

Ruby 的嵌入字符串只能在雙引號中使用,因爲解釋器會原樣輸出單引號中的內容。Ruby 的單引號就有點 C# 中的 @"" 的感覺。
# 原樣輸出
#   Company: #@@companyName

print 'Company: #@@companyName'
# 原樣輸出(包括空格和換行)
print '
      Company:     .org
      Employee Id: unknow
'

% 呈現

Ruby 的另一個酷酷的功能就是 % 呈現方法,這是一種替代引號或其它分隔字符的表示方法。下面第一句直接在雙引號內插入雙引號是錯誤的,但使用 % 呈現後就可以直接在字符串內插入雙引號了。
# 錯誤
print "Ruby "% 呈現法""
# 應用 % 呈現方法
print %Q#Ruby "% 呈現"#

在 % 呈現中,Q 是呈現標識、! 是呈現分隔符。呈現標識聲明替代哪種分隔字符,! 則是一個自定義的分隔符。呈現分隔符只要前後一致就可以了,但不能選擇字母和 < 字符做爲呈現分隔符。如果要在呈現方法中插入呈現字符就必須使用 \ 字符。
# 正確
print %Q~Ruby "% 呈現"~
print %Q.Ruby "% 呈現".
print %Q*Ruby "% 呈現"*
# 在 % 呈現中插入呈現分隔符
print %Q*\* Ruby "% 呈現"*
# 錯誤
print %Q** Ruby "% 呈現"*
print %QbRuby "% 呈現"b
print %Q<Ruby "% 呈現"<

% 呈現列表
  • %Q 替代雙引號 => %Q#Ruby "% 呈現"# 等同於 "Ruby \"% 呈現\""
  • %q 替代單引號
  • %r 替代正則表達式 => %r#([\d\w/])*# 等同於 /([\d\w\/)*/
  • %s 使嵌入字符串、符號失效 => print %s@#{__LINE__}@ 原樣輸出
  • %w 替代字符串數組
在Ruby語言中到處充斥着語法糖衣,有很多的慣用表示法,對於初學者來說,往往被這些技巧 搞得暈頭轉向。 
這兩天看Rails源碼中的Rakefile時,遇到一句代碼:%x( mysqladmin --user=#{MYSQL_DB_USER} create activerecord_unittest ),雖然大概能猜到這句話是幹什麼的,但是Ruby中到底還有多少種以這樣的%開頭的表示 呢? 
相信大家看到最多的應該是:%w,%,%q...下面是我收集的一些%表示法,希望對大家有幫助。 

%{String}  用於創建一個使用雙引號括起來的字符串 
%Q{String} 用於創建一個使用雙引號括起來的字符串 
%q{String} 用於創建一個使用單引號括起來的字符串 
%r{String} 用於創建一個正則表達式字面值 
%w{String} 用於將一個字符串以空白字符切分成一個字符串數組,進行較少替換 
%W{String} 用於將一個字符串以空白字符切分成一個字符串數組,進行較多替換 
%s{String} 用於生成一個符號對象 
%x{String} 用於執行String所代表的命令 

PS:上面幾個%表示法中用{}擴住了String,其實這個{} 只是一種分割符,可以換成別的字符,比如(),那麼%表示法就是%(String),當然還可以是別的字符,對於非括號類型的分割符,左右兩邊要相同, 如%!String! 

下面我對這些表示法簡單舉幾個例子: 

%{String}用於創建一個使用雙引號括起來的字符串 
這個表示法與%Q{String}完全一樣,這邊直接句個例子看結果:
  1. result = %{hello}  
  2. puts "result is: #{result}, Type is:#{result.class}"  
結果: result is: hello, Type is:String 

%Q{String}用於創建一個使用雙引號括起來的字符串 
%q{String}用於創建一個使用單引號括起來的字符串 
從說明中可以看出這兩個表示法的區別就是一個使用雙引號,一個使用單引號。使用雙引號的字符串會對字符串中的變量做較多替換,而單引號則做較少的替換,具 體看例子。先看%Q{String}: 

  1. world = "world"  
  2. result = %Q{hello #{world}}  
  3. puts "result is: #{result}, Type is:#{result.class}"  
結果: result is: hello world, Type is:String 

換成%q{String}: 

  1. world = "world"  
  2. result = %q{hello #{world}}  
  3. puts "result is: #{result}, Type is:#{result.class}"  
結果: 
result is: hello #{world}, Type is:String 

從上面的結果可以看出,較少替換的情況下,#{world}被解析成了字符串,而不會去計算這個變量中的值。 

%r{String}用於創建一個正則表達式字面值 
就像使用/reg/方式一樣,看代碼: 

  1. result = %r{world}  
  2. puts result =~ "hello world"  
  3. puts "result is: #{result}, Type is:#{result.class}"  
結果: 6 
result is: (?-mix:world), Type is:Regexp 

可以看出,world從第6個字符開始匹配 

%w{String}用於將一個字符串以空白字符切分成一個字符串數組,進行較少替換 
%W{String}用於將一個字符串以空白字符切分成一個字符串數組,進行較多替換 
這兩個應該是大家見過最多的,用這個方式構造數組,可以省下一些逗號,Ruby真 是會慣壞大家,以後大家都不用標點符號了。 
同樣給一個簡單的例子: 

  1. result = %w{hello world}  
  2. puts "result is: #{result}, Type is:#{result.class}, length is:#{result.length}"  
結果: result is: helloworld, Type is:Array, length is:2 

%s{String}用於生成一個符號對象 
直接先上代碼: 
  1. result = %s{hello world}  
  2. puts "result is: #{result}, Type is:#{result.class}"  
  3. sym = :"hello world"  
  4. puts "the two symbol is the same: #{sym == result}"  
結果: 
result is: hello world, Type is:Symbol 
the two symbol is the same: true 

可以看出,這兩中方式生成的symbol對象完全一樣 

%x{String}用於執行String所代表的命令 
比如: 
%x{notepad.exe}可以啓動windows下的記事本,這裏我就不列結果了(那是一個大家熟悉的窗口)。

 

ruby文件讀寫的好文章 ruby way之IO之一

原:http://blog.csdn.net/passionboyxie/article/details/7377717
http://simohayha.javaeye.com/blog/153398
1 打開和關閉一個文件 
類方法File.new 打開一個文件,並將它實例化爲一個File對象,他的第一個參數是文件名. 
可選的第二個參數叫做 mode string(這個也是從c得來的).他的意思是怎樣打開一個文件(讀,寫或者其他的).默認是'r'(也就是讀). 
Ruby代碼
  1. file1 = File.new("one")       # Open for reading  
  2.   
  3. file2 = File.new("two","w")  # Open for writing  
[ruby] view plaincopy
  1. file1 = File.new("one")       # Open for reading  file2 = File.new("two", "w")  # Open for writing  
另外一種new的形式是三個參數的,其中第二個參數是指定了這個文件的原始的權限(經常表示爲一個八進制的數).第三個參數是一系列Ored標誌 的組合.標誌是個常量比如File:CREAT(如果文件不存在則創建它)和File:RDONLY(以只讀方式打開文件)。不過這種形式很少使用:

Ruby代碼
  1. file = File.new("three", 0755,File::CREAT|File::WRONLY)  
[ruby] view plaincopy
  1. file = File.new("three", 0755, File::CREAT|File::WRONLY)  


出於對操作系統和運行環境的考慮,如果你打開了一個文件的話,你就必須關閉它。當你打開一個文件用於寫時,你更應該這樣做,從而才能免於丟失數據.close方法就是關閉一個文件:

Ruby代碼
  1. out = File.new("captains.log","w")  
  2. # Process as needed...  
  3. out.close  
[ruby] view plaincopy
  1. out = File.new("captains.log""w"# Process as needed... out.close  

這裏還有一個open方法,它的最簡單的形式是和new同義的: 
Ruby代碼
  1. trans = File.open("transactions","w")  
[ruby] view plaincopy
  1. trans = File.open("transactions","w")  


但是open方法還能夠帶一個block作爲參數,當存在block時,打開的文件將會做爲一個參數傳遞給block.這時這個文件將會在這個block的作用域裏,保持打開,直到block結束時,自動關閉:

Ruby代碼
  1. File.open("somefile","w")do |file|  
  2.    file.puts "Line 1"  
  3.    file.puts "Line 2"  
  4.    file.puts "Third and final line"  
  5. end  
[ruby] view plaincopy
  1. File.open("somefile","w"do |file|   file.puts "Line 1"   file.puts "Line 2"   file.puts "Third and final line" end  


2 更新文件 

假設我們想要打開一個文件用於讀和寫,簡單的加一個'+'號到file mode就行了: 
Ruby代碼
  1. f1 = File.new("file1","r+")  
  2. # Read/write, starting at beginning of file.  
  3. f2 = File.new("file2","w+")  
  4. # Read/write; truncate existing file or create a new one.  
  5. f3 = File.new("file3","a+")  
  6. # Read/write; start at end of existing file or create a  
  7. # new one.  
[ruby] view plaincopy
  1. f1 = File.new("file1""r+"# Read/write, starting at beginning of file. f2 = File.new("file2", "w+") # Read/write; truncate existing file or create a new one. f3 = File.new("file3", "a+") # Read/write; start at end of existing file or create a # new one.  


3 追加一個文件 

假設我們想要追加一段信息到一個存在文件,當我們打開文件時使用'a'作爲file mode就行了: 

Ruby代碼
  1. logfile = File.open("captains_log","a")  
  2. # Add a line at the end, then close.  
  3. logfile.puts "Stardate 47824.1: Our show has been canceled."  
  4. logfile.close  
[ruby] view plaincopy
  1. logfile = File.open("captains_log""a"# Add a line at the end, then close. logfile.puts "Stardate 47824.1: Our show has been canceled." logfile.close  


4隨機存取一個文件 

如果你想隨即存取一個文件,你能夠使用seek方法,它是File從Io繼承而來的.它的最簡單的使用就是指定一個字節位置.這個位置是相對於文件開始的位置(開始的位置是0):
Ruby代碼
  1. # myfile contains only: abcdefghi  
  2. file = File.new("myfile")  
  3. file.seek(5)  
  4. str = file.gets                   # "fghi"  
[ruby] view plaincopy
  1. # myfile contains only: abcdefghi file = File.new("myfile") file.seek(5) str = file.gets                   # "fghi"  


如果你能確定每一行都是固定的長度,你就能seek指定的行: 
Ruby代碼
  1. # Assume 20 bytes per line.  
  2. # Line N starts at byte (N-1)*20  
  3. file = File.new("fixedlines")  
  4. file.seek(5*20)                   # Sixth line!  
  5. # Elegance is left as an exercise.  
[ruby] view plaincopy
  1. # Assume 20 bytes per line. # Line N starts at byte (N-1)*20 file = File.new("fixedlines") file.seek(5*20)                   # Sixth line! # Elegance is left as an exercise.  
如果你想做一個相對的搜索,你就要使用第二個參數,常量 IO::SEEK_CUR表示當前的位置,而第一個參數則就是相對於當前位置的偏移量(可能是負數):

Ruby代碼
  1. file = File.new("somefile")  
  2. file.seek(55)                 # Position is 55  
  3. file.seek(-22, IO::SEEK_CUR)  # Position is 33  
  4. file.seek(47, IO::SEEK_CUR)   # Position is 80  
[ruby] view plaincopy
  1. file = File.new("somefile") file.seek(55)                 # Position is 55 file.seek(-22, IO::SEEK_CUR)  # Position is 33 file.seek(47, IO::SEEK_CUR)   # Position is 80  


你也能從文件的結束位置開始搜索: 

Ruby代碼
  1. file.seek(-20, IO::SEEK_END)  # twenty bytes from eof  
[ruby] view plaincopy
  1. file.seek(-20, IO::SEEK_END)  # twenty bytes from eof  
方法tell得到文件的當前位置,pos是它的別名: 

Ruby代碼
  1. file.seek(20)  
  2. pos1 = file.tell             # 20  
  3. file.seek(50, IO::SEEK_CUR)  
  4. pos2 = file.pos              # 70  
[ruby] view plaincopy
  1. file.seek(20) pos1 = file.tell             # 20 file.seek(50, IO::SEEK_CUR) pos2 = file.pos              # 70  
rewind方法將會將文件指針的位置設回到開始的位置,也就是0. 

5 操作二進制文件 

在很久以前,c語言通過在file mode後附加一個'b'來表示將文件用二進制模式打開.在今天,二進制文件的處理已經沒有那麼麻煩了。在ruby中,一個字符串很容易保存一個二進制數據,而且也不用通過任何特殊的方式來讀文件.

可是在windows下是例外,在他下面,二進制文件和文本文件的不同是,在二進制mode下,結束行不能被轉義爲一個單獨的換行,而是被保存爲一個回車換行對. 
另外的不同是,在文本模式下 control-Z被作爲文件的結束: 

Ruby代碼
  1. # Create a file (in binary mode)  
  2. File.open("myfile","wb") {|f| f.syswrite("12345\0326789\r") }  
  3. # Above note the embedded octal 032 (^Z)  
  4. # Read it as binary  
  5. str = nil  
  6.   
  7. File.open("myfile","rb") {|f| str = f.sysread(15) }  
  8. puts str.size           # 11  
  9. # Read it as text  
  10. str = nil  
  11. File.open("myfile","r") {|f| str = f.sysread(15) }  
  12. puts str.size           # 5  
[ruby] view plaincopy
  1. # Create a file (in binary mode) File.open("myfile","wb") {|f| f.syswrite("12345\0326789\r") } # Above note the embedded octal 032 (^Z) # Read it as binary str = nil  File.open("myfile","rb") {|f| str = f.sysread(15) } puts str.size           # 11 # Read it as text str = nil File.open("myfile","r") {|f| str = f.sysread(15) } puts str.size           # 5  
這邊注意,這些代碼都是在windows下才會打印出後面的結果,如果是在linux兩處都會打印出11. 
再看下面的代碼: 
Ruby代碼
  1. # Input file contains a single line: Line 1.  
  2. file = File.open("data")  
  3. line = file.readline             # "Line 1.\n"  
  4. puts "#{line.size} characters."   # 8 characters  
  5. file.close  
  6. file = File.open("data","rb")  
  7. line = file.readline             # "Line 1.\r\n"  
  8. puts "#{line.size} characters."   # 9 characters 二進制模式的結尾是一個回車換行對.  
  9. file.close  
[ruby] view plaincopy
  1. # Input file contains a single line: Line 1. file = File.open("data") line = file.readline             # "Line 1.\n" puts "#{line.size} characters."  # 8 characters file.close file = File.open("data","rb") line = file.readline             # "Line 1.\r\n" puts "#{line.size} characters."  # 9 characters 二進制模式的結尾是一個回車換行對. file.close  
binmode方法能夠轉換當前的流爲二進制模式,這邊要注意的是,一旦切換過去,就不能切換回來了: 
Ruby代碼
  1. file = File.open("data")  
  2. file.binmode  
  3. line = file.readline             # "Line 1.\r\n"  
  4. puts "#{line.size} characters."   # 9 characters  
  5. file.close  
[ruby] view plaincopy
  1. file = File.open("data") file.binmode line = file.readline             # "Line 1.\r\n" puts "#{line.size} characters."  # 9 characters file.close  
如果你想使用更底層的輸入輸出,那你可以選擇sysread和syswrite方法,他們接受一定數量的字節作爲參數 . 
Ruby代碼
  1. input = File.new("myfile",'a+')  
  2. output = File.new("outfile",'a+')  
  3. instr = input.sysread(10);  
  4. puts instr  
  5. bytes = output.syswrite("This is a test.")  
[ruby] view plaincopy
  1. input = File.new("myfile",'a+') output = File.new("outfile",'a+') instr = input.sysread(10); puts instr bytes = output.syswrite("This is a test.")  

如果文件指針已經到達文件的結尾時,sysread方法將會拋出一個異常. 

這邊要注意 Array 的pack和string的unpack方法,對於處理二進制數據非常有用. 

=======================================================

讀文件:
第一種方法:
$result='d:\\rs.txt'
File.open($result, "r") do |file|  
file.each_line do |line|
     if line.length>20
     puts line.chop.length    #去掉最後一個換行字符,並顯示該行實際字符串的長度
      puts line
    end
  end
  end
第二種方法:
filename='d:\\rs.txt'
while File.exists?(filename) #如果源文件存在就執行下面的操作
file=File.open(filename,'r')
  while (lines=file.gets)
puts lines
end


寫文件:
$filename="C:\\Automation\\rss"+".txt"
$logfile = File.new($filename,"a")
iCount=0

while(iCount<10)      //循環寫入10行
$logfile.puts "http://xxxx/rs#{iCount}.xml"
iCount=iCount+1
end

今天又笨了一次,由於要比較兩個文件的不同,於是考慮用ruby來寫個腳本

實現,剛開始的時候使用雙重
File.open($file1, "r") do |file1|  
file1.each_line do |line1|
總是報錯,

後來改成先把文件讀到一個數組裏,然後循環比較,成功.

其實這是個笨方法,在unix下使用三個命令就可以完成了.

1.先使用sort指令將文件中的數據按照要求的索引進行排序,
2.然後使用uniq指令將重複數據去掉
3.再使用diff命令就可以了.

========================================

ruby讀寫文本文件的簡單例子,除了演示文本文件的讀寫外,這段ruby程序可以從文本文件中刪除包含某些字符串的行。
用法:ruby delline.rb 文件名 字符串1 字符串2 字符串n
將刪除同時包含字符串1 字符串2 字符串n的行。
ruby的開發環境這裏下載
http://www.ruby-lang.org/en/downloads/
直接下載最近的穩定版Windows安裝包
http://rubyforge.org/frs/download.php/29263/ruby186-26.exe

代碼如下

下載: delline.rb
  1. ifARGV.length<2then
  2.   puts "USAGE: ruby delline.rb text_file_name str1 [str2 ...]"
  3.   exit
  4. end
  5.  
  6. i_file_name = ARGV[0]
  7. i_file_name_bak = i_file_name +".bak"
  8. if FileTest.exist?(i_file_name)then
  9.   File.rename(i_file_name,i_file_name_bak)
  10. else
  11.   puts "File #{i_file_name} was not found"
  12.   exit
  13. end
  14.  
  15. i_file = File.new(i_file_name_bak,"r")
  16. o_file = File.new(i_file_name,"w")
  17.  
  18. i_file.each_line do |line|
  19.   delete_flag =true
  20.   1.upto(ARGV.length - 1) do |x|
  21.     if !line.include?(ARGV[x]) then
  22.       delete_flag =false
  23.       break
  24.     end
  25.   end
  26.   o_file.puts lineif !delete_flag
  27. end
  28.  
  29. i_file.close
  30. o_file.close

 File.open("cmd.txt","r") do |file|
while line=file.gets
puts line
end

end

puts

file=File.new("cmd.txt","r")
file.each_line do |line|
puts line 

end



IO.foreach("cmd.txt") do |line|   
   puts line if line =~ /target/   
   puts line if line !~ /target/ 
end 
   
# Another way...   
file = File.new("cmd.txt")   
file.each do |line|   
   puts line if line =~ /target/   

end 



arr = IO.read("cmd.txt")   

bytes = arr.size 
puts "myfile has #{bytes} bytes in it." 



arr = IO.readlines("cmd.txt") 
puts arr 
lines = arr.size   
puts "myfile has #{lines} lines in it." 



file2=File.new("cmd.txt");

puts File.expand_path("cmd.txt")

file = File.new("cmd.txt")   
e_count = 0   
file.each_byte do |byte|   
e_count += 1 if byte == ?e

end 

puts File.exist?("testR.txt")
file1=File.new("testR.txt","w") #沒有文件則會自動創建
puts File.exist?("testR.txt")
puts file1.write("ttt333\nttt444\n")


字符串當文件用.rb
require 'stringio' 
   
ios = StringIO.new("abcdefghijkl\nABC\n123")   
   
ios.seek(5)   
ios.puts("xyz")   

puts ios.tell             # 8   

puts ios.string.dump      # "abcdexyzijkl\nABC\n123"   
   
c = ios.getc   
puts "c = #{c}"           # c = 105   

ios.ungetc(?w)   

puts ios.string.dump      # "abcdexyzwjkl\nABC\n123"   

puts "Ptr = #{ios.tell}" 

s1 = ios.gets             # "wjkl"   
s2 = ios.gets             # "ABC" 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章