<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # **第 3 章 創建命令** 本章介紹 Ruby 從命令行讀取并處理數據的方法。另外,作為第 1 部分的總結,讓我們來實際體驗一下如何用 Ruby 實現 Unix 的 grep 命令,以便大家了解用 Ruby 編寫程序的大概流程。 ### **3.1 命令行的輸入數據** 到目前為止,我們寫的程序都是向屏幕輸出數據。現在我們考慮一下怎么輸入數據。在創建命令前,我們首先得知道怎么使用命令。那么,讓我們先來看看怎么把數據傳遞給程序。 向程序傳遞數據,最簡單的方法就是使用命令行。Ruby 程序中,使用 `ARGV` 這個 Ruby 預定義好的數組來獲取從命令行傳遞過來的數據。數組 `ARGV` 中的元素,就是在命令行中指定的腳本 字符串參數。 在命令行指定多個腳本參數時,各參數之間用空格間隔。 **代碼清單 3.1 print_argv.rb** ~~~ puts "首個參數: #{ARGV[0]}" puts "第2 個參數: #{ARGV[1]}" puts "第3 個參數: #{ARGV[2]}" ~~~ > **執行示例** ~~~ > ruby print_argv.rb 1st 2nd 3rd 首個參數: 1st 第 2 個參數: 2nd 第 3 個參數: 3rd ~~~ 使用數組 `ARGV` 后,程序需要用到的數據就不必都寫在代碼中。同時,抽取數據、保存數據等普通的數組操作對于 `ARGV` 都是適用的。 **代碼清單 3.2 happy_birth.rb** ~~~ name = ARGV[0] print "Happy Birthday, ", name, "!\n" ~~~ > **執行示例** ~~~ > ruby happy_birth.rb Ruby Happy Birthday, Ruby! ~~~ 從參數里得到的數據都是字符串,因此如果希望進行運算時,需要對獲得的數據進行類型轉換。把字符串轉換為整數,我們可以使用 `to_i` 方法。 **代碼清單 3.3 arg_arith.rb** ~~~ num0 = ARGV[0].to_i num1 = ARGV[1].to_i puts "#{num0} + #{num1} = #{num0 + num1}" puts "#{num0} - #{num1} = #{num0 - num1}" puts "#{num0} * #{num1} = #{num0 * num1}" puts "#{num0} / #{num1} = #{num0 / num1}" ~~~ > **執行示例** ~~~ > ruby arg_arith.rb 5 3 5 + 3 = 8 5 - 3 = 2 5 * 3 = 15 5 / 3 = 1 ~~~ ### **3.2 文件的讀取** Ruby 腳本除了讀取命令行傳遞過來的字符串參數外,還可以讀取預先寫在文件里的數據。 Ruby 的源代碼中,有一個名為 ChangeLog 的文本文件。文件里面記錄了 Ruby 相關的修改日志。 文件內容如下所示: ~~~ ┊ Mon Feb 27 23:46:09 2012 Yukihiro Matsumoto <matz@ruby-lang.org> * parse.y (opt_bv_decl): allow newline at the end. [ruby-dev:45292] ┊ ~~~ > **備注** Ruby 的源代碼可以從 Ruby 官網下載。ChangeLog 文件可以在 Ruby 的 github 庫里找到。 > - > Ruby 源碼下載地址:[https://www.ruby-lang.org/zh_cn/downloads/](https://www.ruby-lang.org/zh_cn/downloads/) > - > github 上的 ChangeLog 文件地址:[https://raw.github.com/ruby/ruby/v2_0_0_0/ChangeLog](https://raw.github.com/ruby/ruby/v2_0_0_0/ChangeLog) > 我們就利用這個文件,練習一下用 Ruby 如何進行文件操作。 ### **3.2.1 從文件中讀取內容并輸出** 首先,我們先做一個簡單文件內容讀取程序。讀取文件內容的流程,如下所示: ① **打開文件。** ② **讀取文件的文本數據。** ③ **輸出文件的文本數據。** ④ **關閉文件。** 程序代碼如下: **代碼清單 3.4 read_text.rb** ~~~ 1: filename = ARGV[0] 2: file = File.open(filename) # ① 3: text = file.read # ② 4: print text # ③ 5: file.close # ④ ~~~ 與之前的例子相比,這個例子的代碼終于有點程序的模樣了,接下來我們逐行分析。 第 1 行,將命令行參數 `ARGV[0]` 賦值給變量 `filename`。也就是說,`filename` 表示我們希望讀取的文件名。 第 2 行,`File.open(filename)` 表示打開名為 `filename` 的文件,并返回讀取該文件所需的對象。可能會有讀者不太明白什么是“讀取該文件所需的對象”,不過不要緊,目前我們暫時只需要知道有這么一個對象就可以了。我們會在第 17 章中詳細說明這個對象。 “讀取該文件所需的對象”實際在第 3 行使用。在這里,`read` 方法讀取文本數據,并將讀取到的數據賦值給 `text` 變量。接下來,第 4 行的代碼會輸出 `text` 的文本數據。到目前為止,我們使用過好多次 `print` 方法了,大家應該不會陌生了吧。然后,程序執行最后一段代碼的 `close` 方法。這樣,就可以關閉之前打開了的文件了。 像下面那樣執行這個程序后,指定的文件內容會一下子全部輸出到屏幕中。 **> `ruby read_text.rb` 文件名** 其實,如果只是讀取文件內容,直接使用 `read` 方法會使程序更簡單。 **代碼清單 3.5 read_text_simple.rb** ~~~ 1: filename = ARGV[0] 2: text = File.read(filename) 3: print text ~~~ 關于 `File.read` 方法的詳細用法,我們會在第 17 章進行說明。 更進一步,如果不使用變量,一行代碼就可以搞定了。 **代碼清單 3.6 read_text_oneline.rb** ~~~ 1: print File.read(ARGV[0]) ~~~ ### **3.2.2 從文件中逐行讀取內容并輸出** 現在,我們了解了如何使用 Ruby 讀取并輸出文件里的所有內容。但是,剛才的程序有如下的問題: - **一下子讀取全部文件內容會很耗時;** - **讀取文件的內容會暫時保存在內存中,遇到大文件時,程序有可能因此而崩潰。** 例如一個文件有 100 萬行數據,我們只希望讀取其最初的幾行。這種情況下,如果程序不管三七二十一讀取文件的全部內容,無論從時間還是內存角度來講,都是嚴重的浪費。 因此,我們只能放棄“讀取文件全部內容”的做法(圖 3.1),將代碼清單 3.4 的程序改為逐行讀取并輸出(代碼清單 3.7)。這樣,只需要具備當前行數據大小的內存就足夠了。 ![{%}](https://box.kancloud.cn/2015-10-26_562e01d8b9826.png) **圖 3.1 read 方法和 each_line 方法的區別** **代碼清單 3.7 read_line.rb** ~~~ 1: filename = ARGV[0] 2: file = File.open(filename) 3: file.each_line do |line| 4: print line 5: end 6: file.close ~~~ 程序的第 1 行和第 2 行與代碼清單 3.4 是一樣的,從第 3 行開始有了變化。程序的第 3 行到第 5 行使用了 `each_line` 方法。 `each_line` 方法很像第 2 章介紹的 `each` 方法。`each` 方法是用于逐個處理數組元素,顧名思義,`each_line` 方法就是對文件進行逐行處理。因此在這里,程序會逐行讀取文件的內容,使用 `print` 方法輸出該行的文件內容 `line`,直到所有行的內容輸出完為止。 ### **3.2.3 從文件中讀取指定模式的內容并輸出** Unix 中有一個叫 grep 的命令。grep 命令利用正則表達式搜索文本數據,輸出按照指定模式匹配到的行。我們試試用 Ruby 實現 grep 命令(代碼清單 3.8)。 **代碼清單 3.8 simple_grep.rb** ~~~ 1: pattern = Regexp.new(ARGV[0]) 2: filename = ARGV[1] 3: 4: file = File.open(filename) 5: file.each_line do |line| 6: if pattern =~ line 7: print line 8: end 9: end 10: file.close ~~~ 命令行輸入以下命令,執行代碼清單 3.8。 **> `ruby simple_grep.rb` 模式 文件名** 程序有點長,我們逐行分析一下。 Ruby 執行該腳本時,需要有兩個命令行參數——`ARGV[0]` 和 `ARGV[1]`。第 1 行,程序根據第 1 個參數創建了正則表達式對象,并賦值給變量 `pattern`。`Regexp.new`(*str*) 表示把字符串 *str* 轉換為正則表達式對象。接著第 2 行,把第 2 個參數賦值給作為文件名的變量 `filename`。 第 4 行,打開文件,創建文件對象,并將其賦值給變量 `file`。 第 5 行,與代碼清單 3.7 一樣,讀取一行數據,并將其賦值給變量 `line`。 第 6 行,使用 `if` 語句,判斷變量 `line` 的字符串是否匹配變量 `pattern` 的正則表達式。如果匹配,則在程序第 7 行輸出該字符串。這個 `if` 語句沒有 `else` 部分,因此,若不匹配程序什么都不會做。程序循環讀取文件,重復以上操作。 假設我們希望輸出 Changelog 文件中含有 `matz` 的行,可以執行以下命令: ~~~ > ruby simple_grep.rb matz Changelog ~~~ matz 是松本行弘先生的昵稱,這樣我們就可以輕松找到他的修改之處了。 ### **3.3 方法的定義** 到目前為止,我們用過很多 Ruby 的方法了,其實我們也能定義方法。定義方法的語法如下所示: **`def` 方法名  希望執行的處理 `end`** 假設我們需要定義一個輸出“`Hello, Ruby.`”的方法。 ~~~ def hello print "Hello, Ruby.\n" end ~~~ 執行這 3 行代碼的程序,實際并不會輸出任何結果。這是由于在調用 `hello` 方法前,程序就已經結束了。因此方法定義好后,我們還要通過“調用”告訴 Ruby,我們要執行這個方法。 **代碼清單 3.9 hello_ruby2.rb** ~~~ 1: def hello 2: puts "Hello, Ruby" 3: end 4: 5: hello() ~~~ > **執行示例** ~~~ > ruby hello_ruby2.rb Hello, Ruby ~~~ 執行 `hello()` 調用了 `hello` 方法后,程序就會執行第 1 ~ 3 行定義的內容。 ### **3.4 其他文件的引用** 有時,我們希望在其他的程序里也能重復使用程序的某部分。例如,在某個程序里寫好某個方法,在其他程序里也可以調用。 大部分的編程語言都提供了把多個不同程序組合為一個程序的功能。像這樣,被其他程序引用的程序,我們稱為庫(library)。 Ruby 使用 `require` 方法來引用庫。 **`require` 希望使用的庫名** 庫名可以省略后綴 .rb。 調用 `require` 方法后,Ruby 會搜索參數指定的庫,并讀取庫的所有內容(圖 3.2)。庫內容讀取完畢后,程序才會執行 `require` 方法后面的處理。 ![{%}](https://box.kancloud.cn/2015-10-26_562e01d8d1f37.png) **圖 3.2 庫與引用庫的程序** 我們來實際操作一下,將剛才已經完成的 simple_grep.rb 作為庫提供給其他程序引用。作為庫的文件不用做特別的修改,我們只需把定義了 `simple_grep` 方法的文件(代碼清單 3.10),和引用該文件的程序文件(代碼清單 3.11)放在同一個文件夾即可。 **代碼清單 3.10 grep.rb** ~~~ def simple_grep(pattern, filename) file = File.open(filename) file.each_line do |line| if pattern =~ line print line end end file.close end ~~~ **代碼清單 3.11 use_grep.rb** ~~~ require "./grep" # 讀取grep.rb(省略“.rb”) pattern = Regexp.new(ARGV[0]) filename = ARGV[1] simple_grep(pattern, filename) # 調用simple_grep 方法 ~~~ 這里,程序把執行 `simple_grep` 方法時所需要的檢索模式以及文件名兩個參數,分別賦值給 `pattern` 變量以及 `filename` 變量。請注意,在這個例子里,use_grep.rb 引用了在 grep.rb 定義的 `simple_grep` 方法。與代碼清單 3.8 一樣,執行以下命令輸出 Changelog 文件里包含 `matz` 字符串的行。 ~~~ > ruby use_grep.rb matz Changelog ~~~ > **注** 庫與腳本放在同一文件夾時,需要用`./`來明示文件存放在當前目錄。 Ruby 提供了很多便利的標準庫,在我們的程序需要用到時,都可以使用 `require` 方法加以引用。 例如,我們的程序可以引用 `date` 庫,這樣程序就可以使用返回當前日期的 `Date.today` 的方法,或者返回指定日期對象的 `Date.new` 方法。下面是一個求從 Ruby 的生日—— 1993 年 2 月 24 日到今天為止的天數的小程序。關于 `date` 庫,我們將會在第 20 章詳細說明。 ~~~ require "date" days = Date.today - Date.new(1993, 2, 24) puts(days.to_i) #=> 7396 ~~~ > **專欄** > **pp 方法** > Ruby 除了提供 `p` 方法外,還提供了一個有類似作用的方法——`pp`。`pp` 是英語 pretty print 的縮寫。使用 `pp`方法,我們需要使用 `require` 方法引用 `pp` 庫。 > **代碼清單 p_and_pp.rb** ~~~ require "pp"   v = [{ key00: "《Ruby 基礎教程 第4 版》", key01: "《Ruby 秘笈》", key02: "《Rails3 秘笈》" }] p v pp v ~~~ > > **執行示例** ~~~ > ruby p_and_pp.rb [{:key00=>"《Ruby 基礎教程 第4 版》", :key01=>"《Ruby 秘笈》", :key02=>"《Rails3 秘笈》"}] [{:key00=>"《Ruby 基礎教程 第4 版》", :key01=>"《Ruby 秘笈》", :key02=>"《Rails3 秘笈》"}] ~~~ > 與 `p` 方法有點不同,`pp` 方法在輸出對象的結果時,為了更容易看懂,會適當地換行以調整輸出結果。建議像本例的散列那樣,在需要確認嵌套的內容時使用 `pp` 方法。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看