Достопочтенный sed
awk
В руках мастера эти электроинструменты могут сгибать текст практически в любую форму. К сожалению, я не мастер. Что еще более важно, я действительно не хочу тратить слишком много времени на изучение sed
awk
bash
Введите Ru . Ru, давайте, ленивый программист Ruby, используйте ваш любимый язык программирования в оболочке. Это означает, что вы можете map
sum
capitalize
В этой статье мы рассмотрим некоторые изящные вещи, которые 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
В этом случае нам нужно вызвать join
JSON.parse
String
Очевидно, что набирать так много, чтобы получить предварительное подтверждение JSON, — это большая проблема. Прежде чем вы начнете сам завидовать Python, у Ru есть хорошая хитрость — ru save
С ru save
% 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, зайдите на официальную страницу . Есть несколько отличных примеров, таких как:
Спасибо за прочтение!