Computer >> Máy Tính >  >> Lập trình >> Ruby

Nâng cấp Command-Line-Fu của bạn với Ruby

Để thực sự thành thạo dòng lệnh, bạn phải thông thạo hàng chục - nếu không muốn nói là hàng trăm - chương trình tiện ích nhỏ. Mỗi thứ trong số này thực hiện những điều hơi khác nhau. Nó có thể khá áp đảo.

May mắn thay, có thể thay thế rất nhiều công cụ mục đích đơn lẻ này bằng một ngôn ngữ lập trình mục đích chung như Ruby. Bằng cách đó, bạn có thể sử dụng kiến ​​thức Ruby mà bạn đã có để nâng cấp dòng lệnh-fu của mình.

Bài đăng này sẽ đưa bạn qua các nguyên tắc cơ bản của việc sử dụng Ruby như một con dao quân đội thụy sỹ dòng lệnh. Tôi sẽ không bắn phá bạn bằng những câu nói khéo léo. Thay vào đó, chúng ta sẽ xem xét mọi thứ thực sự hoạt động như thế nào, để hy vọng rằng bạn sẽ có thể áp dụng những kỹ thuật này để giải quyết vấn đề của chính mình.

Sử dụng Ruby từ dòng lệnh

Tôi chắc rằng bạn biết rằng bạn có thể chạy các chương trình Ruby từ dòng lệnh như vậy:

$ ruby myprogram.rb

Nhưng bạn có biết rằng bạn có thể viết mã để được thực thi bởi Ruby không?

$ echo "puts 2+2" | ruby
4

Thậm chí hữu ích hơn là khả năng chuyển mã dưới dạng đối số dòng lệnh. Đây là những gì chúng ta sẽ dành thời gian cho ngày hôm nay.

$ ruby -e 'puts 2+2'
4

Xin chào người mới

Các ví dụ trên có khó hiểu không? Có thể do bạn chưa quen với đường ống và chuyển hướng. Kiểm tra bài đăng này để có một phần giới thiệu tốt. Chúng tôi sẽ sử dụng nhiều đường ống bên dưới.

Làm việc với đầu vào

Hầu hết các công cụ dòng lệnh lấy một số dữ liệu, xử lý và sau đó loại bỏ nó.

Chúng tôi có hai tùy chọn tốt để nhận đầu vào:đối số dòng lệnh và STDIN. Chúng ta hãy xem xét từng người trong số họ.

Đối số dòng lệnh

Bạn có thể gửi bao nhiêu đối số dòng lệnh tùy thích vào tập lệnh của mình. Chỉ cần đặt chúng sau mọi thứ khác:

$ ruby -e '<your code here>' arg1 arg2 arg3 etc

Các đối số này được lưu trữ bên trong ARGV mảng. Trong ví dụ dưới đây, tôi sắp xếp toàn bộ mảng để bạn có thể thấy những gì trong đó.

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

Cần lưu ý rằng đây chính xác là cách Ruby luôn hoạt động. Không có điều kỳ diệu nào xảy ra chỉ vì chúng ta đang sử dụng dòng lệnh. Xem bài đăng này về ARGV để biết thêm chi tiết.

Ví dụ ngu ngốc

Hãy tưởng tượng trong giây lát rằng tôi là người siêu tự cao tự đại. Điều quan trọng nhất đối với tôi là biết bao nhiêu lần tên của tôi được nhắc đến trên mạng. Sử dụng các kỹ thuật mà chúng tôi đã thấy, tôi có thể dễ dàng viết một lớp lót để tính toán điều này cho bất kỳ trang web nào.

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

STDIN

Đối số dòng lệnh rất tốt, nhưng chúng chỉ tốt cho các giá trị ngắn. Bạn sẽ không muốn sử dụng chúng để - nói - nhập vào văn bản không bị ràng buộc của Moby Dick. Vì vậy, chúng tôi muốn sử dụng STDIN.

Nếu bạn không quen thuộc với STDIN, đừng lo lắng. Đối với mục đích của chúng tôi, ở đây nó hoạt động giống như bất kỳ tệp nào khác đang mở để đọc.

Đây là những gì tôi muốn nói. Trong ví dụ dưới đây, chúng tôi đang đưa một số văn bản vào Ruby. Tập lệnh Ruby của chúng tôi đang đọc nó từ STDIN và in nó ra màn hình.

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

Chúng tôi có thể dễ dàng nhập lượng dữ liệu lớn hơn bằng cách sử dụng cat . Ví dụ dưới đây sử dụng first phương thức có sẵn trên bất kỳ tệp nào để lấy vài dòng đầu tiên của văn bản:

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

Ví dụ ngu ngốc

Bây giờ chúng ta đã biết cách sử dụng STDIN, hãy viết lại ví dụ ngu ngốc ở trên. Thay vì sử dụng Ruby để tìm nạp trang web, chúng ta có thể sử dụng curl và chỉ sử dụng Ruby để khớp mẫu.

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

STDIN với đường cú pháp!

Khi bạn đang làm việc với STDIN, việc lặp lại từng dòng đầu vào rất phổ biến. Hãy tưởng tượng rằng tôi muốn lấy phần mở rộng tệp cho mọi tệp trong một thư mục. Đây là cách tôi có thể làm điều đó bằng cách sử dụng vòng lặp STDIN thông thường:

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

Vì vòng lặp STDIN rất phổ biến, nên Ruby cung cấp một cách viết tắt. Nếu chúng tôi chạy tập lệnh của mình với -n cờ, Ruby sẽ tự động lặp qua từng dòng trong STDIN. Dòng hiện tại nằm trong biến toàn cục $_ .

Vì vậy, chúng ta có thể viết lại ví dụ trên như sau:

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

Bạn có muốn sử dụng tốc ký hay không. Mặc dù điều đó chắc chắn có nghĩa là bạn phải viết ít mã hơn, nhưng cũng có nghĩa là bạn phải nhớ nhiều dữ kiện tùy ý hơn như -n$_ .

Làm việc với đầu ra

Trong những tình huống như thế này, bạn thường sẽ muốn ghi đầu ra của mình vào STDOUT. Điều này sẽ mang lại cho bạn sự linh hoạt nhất vì nó sẽ cho phép bạn chuyển đầu ra vào các chương trình khác hoặc được chuyển hướng đến đĩa khi cần thiết.

Tin tốt là bạn có thể sử dụng các lệnh in tương tự mà bạn có thể rất quen thuộc. Một điều cần lưu ý là puts thêm một dòng mới, có thể có hoặc không như những gì bạn muốn.

puts "hello world" # sends "hello world\n" to STDOUT
print "hello world" # doesn't add a newline"

Tập hợp tất cả lại với nhau

Honeybadger có trụ sở tại bang Washington của Mỹ. Điều đó có nghĩa là chúng tôi có đặc quyền thanh toán thuế bán hàng cho mọi khách hàng thanh toán cũng sống ở Washington.

Tôi đã đơn giản hóa điều này một chút, nhưng về cơ bản chúng tôi có một tệp CSV với mọi giao dịch trong năm. Nó trông giống như sau:

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

Vì vậy, để nhận được một khoản tiền nhanh chóng cho tất cả các giao dịch ở Washington, tôi có thể sử dụng một bảng lót như sau:

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

Hãy nhớ rằng đây là một cách cực kỳ cẩu thả để phân tích cú pháp tệp CSV. Tôi sẽ không bao giờ gửi mã này ra ngoài tự nhiên. Nhưng một trong những niềm vui khi viết các chương trình nhỏ bé nhỏ để giải quyết các vấn đề một lần là bạn có thể bỏ qua tất cả các trường hợp phức tạp. Đó là những gì tôi sẽ làm ở đây.