Статьи

Ру: Рубин в вашей оболочке

Рубин

Достопочтенный sedawk В руках мастера эти электроинструменты могут сгибать текст практически в любую форму. К сожалению, я не мастер. Что еще более важно, я действительно не хочу тратить слишком много времени на изучение sedawkbash

Введите Ru . Ru, давайте, ленивый программист Ruby, используйте ваш любимый язык программирования в оболочке. Это означает, что вы можете mapsumcapitalize В этой статье мы рассмотрим некоторые изящные вещи, которые Ru позволяет вам делать, и как это может упростить ваши задачи по обработке текста.

Установка Ру

Ру поставляется упакованным как рубиновый камень. Чтобы установить Ru, запустите свой терминал:

 % gem install ru                                                            
Successfully installed ru-0.1.4
1 gem installed

Основы

Прежде чем мы перейдем к хорошим моментам, давайте немного узнаем о том, как Ru позволяет нам использовать Ruby для взаимодействия с оболочкой. После установки драгоценного камня мы можем вызвать Ru командой ru Подобно типичным командам Unix, ru

Вот первый пример файла для сегодняшнего исследования:

 % cat a_tale.txt
It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair…

ru

 % ru 'map(&:upcase)' a_tale.txt                                   
IT WAS THE BEST OF TIMES, IT WAS THE WORST OF TIMES, IT WAS THE AGE OF WISDOM, IT WAS THE AGE OF FOOLISHNESS, IT WAS THE EPOCH OF BELIEF, IT WAS THE EPOCH OF INCREDULITY, IT WAS THE SEASON OF LIGHT, IT WAS THE SEASON OF DARKNESS, IT WAS THE SPRING OF HOPE, IT WAS THE WINTER OF DESPAIR

Файл также может быть передан по каналам:

 % cat a_tale.txt | ru 'map(&:upcase)'

На самом деле, неудивительно, что вы можете перенаправить вывод ru Предположим, я хотел посчитать слова:

 % cat a_tale.txt | ru 'map(&:upcase)' | wc -w
60

Это чрезвычайно мощно, поскольку ruпросто еще одна команда Unix, которая принимает ввод и манипулирует его выводом.

Давайте разберемся с основами, давайте перейдем к забавным вещам.

Текст-обработка-фу в ру

Лучший способ почувствовать Ru — это увидеть некоторые примеры или, что еще лучше, попробовать их самостоятельно! Вот файл примера, с которым мы будем работать для следующих нескольких примеров:

 % cat chapters.txt
from zero to deploy
a toy app
mostly static pages
rails-flavored ruby
filling in the layout
modeling users
sign up
log in, log out
updating, showing, and deleting users
account activation and password resets
user microposts
following users

фильтрация

Допустим, я хочу найти заголовки глав, которые могут быть слишком многословными:

 % cat chapters.txt | ru 'select { |l| l.split.size == 5 }'
updating, showing, and deleting users
account activation and password resets

Внутренне Ru читает файл как массив строк. Затем в массив вызывается select { ... } Поскольку это массив, вы можете вызвать любой метод Array .

Пропуск линий

Иногда полезно знать о номерах строк. В этом примере я хочу пропустить нечетные строки и удалить все пустые строки:

 % ru 'map.with_index { |line, index| index % 2 == 0 ? line : "" }' chapters.txt | grep -v '^$'
from zero to deploy
mostly static pages
filling in the layout
sign up
updating, showing, and deleting users
user microposts

Еще раз, Ru не мешает вам комбинировать вывод с существующими командами. Здесь мы используем grep

Titleize и ActiveSupport

Ru поставляется со встроенным ActiveSupport. Это очень мило, потому что он добавляет удобные функции, такие как titleize Это очень полезно для случайного автора статьи, который абсолютно не разбирается в правилах присвоения заголовков:

 % ru 'map(&:titleize)' chapters.txt
From Zero To Deploy
A Toy App
Mostly Static Pages
Rails Flavored Ruby
Filling In The Layout
Modeling Users
Sign Up
Log In, Log Out
Updating, Showing, And Deleting Users
Account Activation And Password Resets
User Microposts
Following Users

(ОК, может быть, это не совсем правильно, но все равно круто…)

Unix VS Ruby

Скажем, я хотел найти топ-10 команд, которые я часто использую. В полностью Unix-стране я мог бы сделать:

 % history | awk '{print $2;}' | sort | uniq -c | sort -rn | head -10

Это возвращает вывод как:

 1737 cd
1052 git
 880 ls
 857 vim
 608 gst
 310 mix
 263 exit
 248 gc
 240 fg
 224 iex

Хотя моя голова интуитивно понимает, что происходит, я не слишком уверен во всех необходимых дополнительных флажках. Кроме того, я обманул и должен был искать StackOverflow для вышеуказанного заклинания.

Вот эквивалент в Ru:

 history | ru 'inject(Hash.new(0)) { |h, l| h[l.split[1]] += 1; h }.sort_by { |k, v| -v }.map(&:first).take(10)'

Ruby великолепен благодаря своему читаемому синтаксису и выразительности, и Rubyist во мне прекрасно понимает, что происходит, даже если он кажется немного более многословным.

JSON Formatter

Мне всегда приходилось претенцировать JSON в какой-то момент во время веб-разработки. Например, возьмите следующий JSON:

 % cat sample.json
{ "id": "0001", "type": "donut", "name": "Cake", "ppu": 0.55, "batters": { "batter": [ { "id": "1001", "type": "Regular" }, { "id": "1002", "type": "Chocolate" }, { "id": "1003", "type": "Blueberry" }, { "id": "1004", "type": "Devil's Food" } ] }, "topping": [ { "id": "5001", "type": "None" }, { "id": "5002", "type": "Glazed" }, { "id": "5005", "type": "Sugar" }, { "id": "5007", "type": "Powdered Sugar" }, { "id": "5006", "type": "Chocolate with Sprinkles" }, { "id": "5003", "type": "Chocolate" }, { "id": "5004", "type": "Maple" } ] }

Python поставляется с отличным инструментом, который делает это:

 cat sample.json | python -m json.tool

Я страдал от некоторой зависти Питона из-за этого. Попробуем добиться аналогичного эффекта в Ru:

 % cat sample.json | ru 'require "json"; JSON.pretty_generate(JSON.parse(files.join))'

Это дает вам ожидаемый предварительно подтвержденный JSON:

 % cat sample.json | ru 'require "json"; JSON.pretty_generate(JSON.parse(files.join))'
{
  "id": "0001",
  "type": "donut",
  "name": "Cake",
  "ppu": 0.55,
  "batters": {
    "batter": [
      {
        "id": "1001",
        "type": "Regular"
      },
      {
        "id": "1002",
        "type": "Chocolate"
      },
      {
        "id": "1003",
        "type": "Blueberry"
      },
      {
        "id": "1004",
        "type": "Devil's Food"
      }
    ]
  },
  "topping": [
    {
      "id": "5001",
      "type": "None"
    },
    {
      "id": "5002",
      "type": "Glazed"
    },
    {
      "id": "5005",
      "type": "Sugar"
    },
    {
      "id": "5007",
      "type": "Powdered Sugar"
    },
    {
      "id": "5006",
      "type": "Chocolate with Sprinkles"
    },
    {
      "id": "5003",
      "type": "Chocolate"
    },
    {
      "id": "5004",
      "type": "Maple"
    }
  ]
}

Здесь есть пара вещей, на которые стоит обратить внимание. Во-первых, мы можем require Посмотрите, как нам снова удалось выполнить предварительную проверку JSON:

 % cat sample.json | ru 'require "json"; JSON.pretty_generate(JSON.parse(files.join))'

До сих пор мы предполагали, что первым аргументом является неявно файл. Однако в этом случае строки в файле фиксируются в методе files В этом случае нам нужно вызвать joinJSON.parseString

Очевидно, что набирать так много, чтобы получить предварительное подтверждение JSON, — это большая проблема. Прежде чем вы начнете сам завидовать Python, у Ru есть хорошая хитрость — ru save С ru save , вы можете назвать команду и сохранить ее. Например, чтобы сохранить префиксатор JSON:

 %  ru save jsonify 'require "json"; JSON.pretty_generate(JSON.parse(files.join))'
Saved command: jsonify is 'require "json"; JSON.pretty_generate(JSON.parse(files.join))'

Затем мы можем запустить команду с помощью команды ru run

 %  cat sample.json | ru run jsonify

Чтобы получить список сохраненных команд, введите ru list

 % ru list
Saved commands:
jsonify require "json"; JSON.pretty_generate(JSON.parse(files.join))

Ru помогает вам упростить рабочий процесс

Хотя я не часто использую Ru, я рад, что он всегда есть в моем наборе инструментов. Чтобы узнать больше о Ru, зайдите на официальную страницу . Есть несколько отличных примеров, таких как:

Спасибо за прочтение!