Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เชี่ยวชาญ Command Line ด้วย Ruby: คู่มือปฏิบัติ

เพื่อ master command line จริงๆ ต้อง master โปรแกรม utility เล็กๆ โหล่หรือร้อยหลายๆ ตัว แต่ละตัวทำงานต่างกันหน่อย อาจ overwhelming ได้

โชคดีที่แทนที่ single-purpose tools หลายตัวด้วย general-purpose programming language เช่น Ruby ได้ ใช้ Ruby knowledge ที่มีอยู่ level up command-line-fu

โพสต์นี้พาคุณผ่าน fundamentals ของ Ruby เป็น command-line swiss army knife ไม่ได้ bombard ด้วย clever one-liners แต่มาดูว่าดีไซน์จริงยังไง เพื่อนำไปแก้ปัญหาของตัวเอง

ใช้ Ruby จาก command line

แน่นอนคุณรู้ว่ารัน Ruby programs จาก command line ได้:


$ ruby myprogram.rb

แต่รู้ไหมว่า pipe code เข้า Ruby ให้ execute ได้?


$ echo "puts 2+2" | ruby
4

มีประโยชน์กว่านั้นคือส่ง code เป็น command-line argument นี่คือสิ่งที่เราจะใช้เวลาวันนี้


$ ruby -e 'puts 2+2'
4

Hey Newbies

ตัวอย่างข้างต้นสับสนไหม? อาจเพราะไม่คุ้น pipes และ redirection ดูโพสต์แนะนำดีๆ เราจะใช้ pipes เยอะด้านล่าง

ทำงานกับ Input

Command-line tools ส่วนใหญ่รับ data ประมวลผล แล้ว吐กลับออกมา

เรามีสองทางดีๆ สำหรับ input: command-line arguments และ STDIN มาดูแต่ละอย่าง

Command-line arguments

ส่ง command-line arguments ได้ไม่จำกัด ใส่หลังทุกอย่าง:


$ ruby -e '' arg1 arg2 arg3 etc

Arguments เก็บอยู่ใน array ARGV ตัวอย่าง dump ทั้ง array:


$ ruby -e 'puts ARGV.inspect' apples bananas pears oranges
["apples", "bananas", "pears", "oranges"]

ควรทราบ: นี่คือพฤติกรรม Ruby ปกติ ไม่มี magic แค่เพราะใช้ command line ดูโพสต์เกี่ยว ARGV รายละเอียด

Dumb example

จินตนาการว่าผม ego มาก สิ่งสำคัญคือรู้ว่าชื่อผมถูก mention บนเว็บกี่ครั้ง ใช้เทคนิคข้างต้น one-liner คำนวณได้สำหรับ webpage ใดๆ:


$ ruby -e "require 'open-uri'; puts open(ARGV.first).read.scan(/starr/i).count" 

STDIN

Command-line arguments ดีแต่สำหรับค่าสั้นๆ ไม่จะเอาไว้ input unabridged text of Moby Dick ใช้ STDIN แทน

ถ้าไม่คุ้น STDIN อย่าตกใจ สำหรับเรา behave เหมือนไฟล์เปิดอ่าน

ตัวอย่าง pipe text เข้า Ruby script อ่านจาก STDIN พิมพ์หน้าจอ:


echo "bananas!" | ruby -e "puts STDIN.read"
bananas!

Input ข้อมูลเยอะได้ด้วย cat ตัวอย่าง用 first method (available บนไฟล์) ดับบรรทัดแรกๆ:


cat moby.txt | ruby -e "puts STDIN.first(3)"
Call me Ishmael. Some years ago--never mind how long precisely--having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of

Dumb example

ตอนรู้ consume STDIN แล้ว rewrite dumb example ข้างบน แทนที่จะ用 Ruby fetch webpage 用 curl Ruby แค่ pattern matching:


curl  | ruby -e "puts STDIN.read.scan(/starr/i).size"

STDIN with syntactic sugar!

เวลาทำงานกับ STDIN มักต้อง loop ทุกบรรทัด จินตนาการอยากได้ file extension ทุกไฟล์ใน directory ทำได้แบบนี้:


ls | ruby -e 'STDIN.each_line { |l| puts l.split(".").last }'
rb
rb
csv

STDIN loop common Ruby มี shorthand รัน script ด้วย flag -n Ruby จะ loop ทุกบรรทัดใน STDIN อัตโนมัติ บรรทัดปัจจุบันอยู่ใน global variable $_

เขียนใหม่ได้:


ls | ruby -n -e 'puts $_.split(".").last'

ขึ้นอยู่กับคุณจะใช้ shorthand หรือไม่ แน่นอนเขียนโค้ดน้อยลง แต่ต้องจำ arbitrary facts เยอะขึ้น เช่น -n และ $_

ทำงานกับ Output

สถานการณ์แบบนี้มักอยากเขียน output ไป STDOUT ให้ flexibility สูงสุด pipe output ไปโปรแกรมอื่นหรือ redirect ลง disk ได้

ข่าวดี: ใช้ print commands เดิมที่คุ้นเคย หนึ่งอย่างตระหนัก: puts เพิ่ม newline อาจจะ/อาจไม่ใช่สิ่งที่ต้องการ


puts "hello world" # ส่ง "hello world\n" ไป STDOUT
print "hello world" # ไม่เพิ่ม newline

รวมทั้งหมดเข้าด้วยกัน

Honeybadger base อยู่ Washington state US หมายความว่าเราจ่าย sales tax ทุก paying customer ที่อยู่ Washington ด้วย

Simple มาก แต่เรามี CSV file ทุก transaction ในปีหนึ่ง คล้ายๆ นี้:


1/1/2015,100.00,WA
1/1/2015,50.00,NY

เพื่อ sum ทุก transactions ใน Washington one-liner แบบนี้:


$ cat cc.csv | ruby -e 'puts STDIN.inject(0) { |sum, x| date, amount, state = x.split(","); state.strip == "WA" ? sum + amount.to_f : sum }'

จำไว้: วิธี parse CSV นี้ sloppy มาก ไม่ส่งโค้ดแบบนี้ production แต่ความสุขของ tiny programs แก้ one-off problems คือ ignore edge cases ได้ นี่คือสิ่งที่ทำที่นี่