หากต้องการเชี่ยวชาญบรรทัดคำสั่งอย่างแท้จริง คุณต้องเชี่ยวชาญโปรแกรมยูทิลิตี้ขนาดเล็กหลายสิบโปรแกรม ถ้าไม่ใช่หลายร้อยโปรแกรม แต่ละสิ่งเหล่านี้ทำสิ่งต่าง ๆ แตกต่างกันเล็กน้อย มันสามารถล้นหลามสวย
โชคดีที่มันเป็นไปได้ที่จะแทนที่เครื่องมืออเนกประสงค์จำนวนมากเหล่านี้ด้วยภาษาการเขียนโปรแกรมเอนกประสงค์ เช่น Ruby ด้วยวิธีนี้คุณสามารถใช้ความรู้ Ruby ที่คุณมีอยู่แล้วเพื่อเพิ่มระดับ command-line-fu ของคุณ
โพสต์นี้จะนำคุณผ่านพื้นฐานของการใช้ Ruby เป็นมีดทหารสวิสบรรทัดคำสั่ง ฉันจะไม่ทิ้งระเบิดคุณด้วยยานบินเดี่ยวที่ฉลาด แต่เราจะดูว่าสิ่งต่าง ๆ ทำงานอย่างไร ดังนั้นหวังว่าคุณจะสามารถใช้เทคนิคเหล่านี้เพื่อแก้ปัญหาของคุณเองได้
การใช้ Ruby จากบรรทัดคำสั่ง
ฉันแน่ใจว่าคุณรู้ว่าคุณสามารถเรียกใช้โปรแกรม Ruby จากบรรทัดคำสั่งดังนี้:
$ ruby myprogram.rb
แต่คุณรู้หรือไม่ว่าคุณสามารถไพพ์โค้ดเพื่อให้ Ruby รันได้?
$ echo "puts 2+2" | ruby
4
มีประโยชน์มากกว่านั้นคือความสามารถในการส่งรหัสเป็นอาร์กิวเมนต์บรรทัดคำสั่ง นี่คือสิ่งที่เราจะใช้เวลาของเราในวันนี้
$ ruby -e 'puts 2+2'
4
สวัสดีมือใหม่
ตัวอย่างข้างต้นทำให้เกิดความสับสนหรือไม่? อาจเป็นเพราะคุณไม่คุ้นเคยกับไปป์และการเปลี่ยนเส้นทาง ตรวจสอบโพสต์นี้สำหรับการแนะนำที่ดี เราจะใช้ท่อด้านล่างมาก
การทำงานกับอินพุต
เครื่องมือบรรทัดคำสั่งส่วนใหญ่จะรับข้อมูลบางส่วน ประมวลผล แล้วคายกลับออกมา
เรามีสองตัวเลือกที่ดีในการรับอินพุต:อาร์กิวเมนต์บรรทัดคำสั่งและ STDIN มาดูกันเลยละกัน
อาร์กิวเมนต์บรรทัดคำสั่ง
คุณสามารถส่งอาร์กิวเมนต์บรรทัดคำสั่งได้มากเท่าที่ต้องการไปยังสคริปต์ของคุณ วางไว้หลังอย่างอื่น:
$ ruby -e '<your code here>' arg1 arg2 arg3 etc
อาร์กิวเมนต์เหล่านี้ถูกเก็บไว้ใน ARGV
อาร์เรย์ ในตัวอย่างด้านล่าง ฉันกำลังทิ้งอาร์เรย์ทั้งหมดเพื่อให้คุณเห็นว่ามีอะไรอยู่ในนั้น
$ ruby -e 'puts ARGV.inspect' apples bananas pears oranges
["apples", "bananas", "pears", "oranges"]
เป็นที่น่าสังเกตว่า Ruby มีพฤติกรรมเช่นนี้อยู่เสมอ ไม่มีสิ่งมหัศจรรย์เกิดขึ้นเพียงเพราะเราใช้บรรทัดคำสั่ง ตรวจสอบโพสต์เกี่ยวกับ ARGV สำหรับรายละเอียดเพิ่มเติม
ตัวอย่างโง่
ลองนึกภาพสักครู่ว่าฉันเป็นคนเห็นแก่ตัวมาก สิ่งที่สำคัญที่สุดสำหรับฉันคือการรู้ว่าชื่อของฉันถูกกล่าวถึงบนเว็บกี่ครั้ง เมื่อใช้เทคนิคต่างๆ ที่เราเห็น ฉันสามารถเขียนบรรทัดเดียวเพื่อคำนวณสิ่งนี้สำหรับหน้าเว็บใดก็ได้
$ ruby -e "require 'open-uri'; puts open(ARGV.first).read.scan(/starr/i).count" <url here>
STDIN
อาร์กิวเมนต์บรรทัดคำสั่งนั้นยอดเยี่ยม แต่ก็ดีสำหรับค่าสั้นๆ เท่านั้น คุณคงไม่อยากใช้มันเพื่อ - พูด - ป้อนข้อความที่ไม่ย่อของ Moby Dick เพื่อที่เราต้องการใช้ STDIN
หากคุณไม่คุ้นเคยกับ STDIN ก็ไม่ต้องเกรงใจ สำหรับจุดประสงค์ของเราที่นี่ มันทำงานเหมือนกับไฟล์อื่นๆ ที่เปิดอ่านได้
นี่คือสิ่งที่ฉันหมายถึง ในตัวอย่างด้านล่าง เรากำลังวางข้อความบางส่วนลงใน Ruby สคริปต์ Ruby ของเรากำลังอ่านจาก STDIN และพิมพ์ไปที่หน้าจอ
echo "bananas!" | ruby -e "puts STDIN.read"
bananas!
เราสามารถป้อนข้อมูลจำนวนมากได้อย่างง่ายดายโดยใช้ cat
. ตัวอย่างด้านล่างใช้ first
วิธีการที่มีอยู่ในไฟล์ใดก็ได้เพื่อดึงข้อความสองสามบรรทัดแรก:
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
ตัวอย่างโง่
ตอนนี้เรารู้วิธีใช้ STDIN แล้ว เรามาลองเขียนตัวอย่างโง่ๆ จากด้านบนกัน แทนที่จะใช้ Ruby เพื่อดึงหน้าเว็บ เราสามารถใช้ curl
และใช้ Ruby ในการจับคู่แพทเทิร์นเท่านั้น
curl <MY URL> | ruby -e "puts STDIN.read.scan(/starr/i).size"
STDIN กับน้ำตาลประโยค!
เมื่อคุณทำงานกับ STDIN เป็นเรื่องปกติที่จะต้องวนรอบอินพุตแต่ละบรรทัด ลองนึกภาพว่าฉันต้องการรับนามสกุลไฟล์สำหรับทุกไฟล์ในไดเร็กทอรี นี่คือวิธีที่ฉันสามารถทำได้โดยใช้ลูป STDIN ปกติ:
ls | ruby -e 'STDIN.each_line { |l| puts l.split(".").last }'
rb
rb
csv
เนื่องจากลูป STDIN เป็นเรื่องปกติดังนั้น Ruby จึงจัดทำชวเลข หากเราเรียกใช้สคริปต์ด้วย -n
ตั้งค่าสถานะ Ruby จะวนซ้ำในแต่ละบรรทัดใน STDIN โดยอัตโนมัติ บรรทัดปัจจุบันอยู่ในตัวแปรส่วนกลาง $_
.
ดังนั้นเราสามารถเขียนตัวอย่างข้างต้นใหม่ได้ดังนี้:
ls | ruby -n -e 'puts $_.split(".").last'
ขึ้นอยู่กับคุณว่าคุณต้องการใช้ชวเลขหรือไม่ แม้ว่าแน่นอนว่าคุณจะต้องเขียนโค้ดน้อยลง แต่ก็หมายความว่าคุณต้องจำข้อเท็จจริงตามอำเภอใจมากขึ้น เช่น -n
และ $_
.
การทำงานกับเอาต์พุต
ในสถานการณ์เช่นนี้ คุณมักจะต้องการเขียนผลลัพธ์ของคุณไปที่ STDOUT วิธีนี้จะทำให้คุณมีความยืดหยุ่นมากที่สุดเพราะจะช่วยให้คุณสามารถไพพ์เอาต์พุตไปยังโปรแกรมอื่นหรือเปลี่ยนเส้นทางไปยังดิสก์ได้ตามความจำเป็น
ข่าวดีก็คือคุณจะได้ใช้คำสั่งพิมพ์เดียวกันกับที่คุณคุ้นเคยเป็นอย่างดี สิ่งหนึ่งที่ต้องระวังคือ puts
เพิ่มบรรทัดใหม่ซึ่งอาจหรือไม่ใช่สิ่งที่คุณต้องการ
puts "hello world" # sends "hello world\n" to STDOUT
print "hello world" # doesn't add a newline"
รวมทุกอย่างเข้าด้วยกัน
Honeybadger ตั้งอยู่ในรัฐวอชิงตันในสหรัฐอเมริกา ซึ่งหมายความว่าเรามีสิทธิ์จ่ายภาษีการขายสำหรับลูกค้าที่ชำระเงินทุกคนที่อาศัยอยู่ในวอชิงตันด้วย
ฉันลดความซับซ้อนของสิ่งนี้ลงเล็กน้อย แต่โดยพื้นฐานแล้วเรามีไฟล์ CSV กับทุกธุรกรรมสำหรับปี หน้าตาประมาณนี้:
1/1/2015,100.00,WA
1/1/2015,50.00,NY
ดังนั้นเพื่อให้ได้ผลรวมอย่างรวดเร็วสำหรับธุรกรรมทั้งหมดในวอชิงตัน ฉันสามารถใช้สายการบินเดียวแบบนี้:
$ cat cc.csv | ruby -e 'puts STDIN.inject(0) { |sum, x| date, amount, state = x.split(","); state.strip == "WA" ? sum + amount.to_f : sum }'
โปรดทราบว่านี่เป็นวิธีที่เลอะเทอะอย่างมากในการแยกวิเคราะห์ไฟล์ CSV ฉันจะไม่ส่งรหัสนี้ออกไปในป่า แต่ความสุขอย่างหนึ่งของการเขียนโปรแกรมเล็กๆ น้อยๆ เพื่อแก้ปัญหาแบบใช้ครั้งเดียวคือ การที่คุณไม่ต้องสนใจเคสที่เป็นขอบทั้งหมด นั่นคือสิ่งที่ฉันจะทำที่นี่