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

เพิ่มระดับ Command-Line-Fu ด้วย Ruby

หากต้องการเชี่ยวชาญบรรทัดคำสั่งอย่างแท้จริง คุณต้องเชี่ยวชาญโปรแกรมยูทิลิตี้ขนาดเล็กหลายสิบโปรแกรม ถ้าไม่ใช่หลายร้อยโปรแกรม แต่ละสิ่งเหล่านี้ทำสิ่งต่าง ๆ แตกต่างกันเล็กน้อย มันสามารถล้นหลามสวย

โชคดีที่มันเป็นไปได้ที่จะแทนที่เครื่องมืออเนกประสงค์จำนวนมากเหล่านี้ด้วยภาษาการเขียนโปรแกรมเอนกประสงค์ เช่น 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 ฉันจะไม่ส่งรหัสนี้ออกไปในป่า แต่ความสุขอย่างหนึ่งของการเขียนโปรแกรมเล็กๆ น้อยๆ เพื่อแก้ปัญหาแบบใช้ครั้งเดียวคือ การที่คุณไม่ต้องสนใจเคสที่เป็นขอบทั้งหมด นั่นคือสิ่งที่ฉันจะทำที่นี่