...

воскресенье, 1 июня 2014 г.

JSON pipes в шелле

Чем больше я пишу однострочники в шелле, тем больше я прихожу к двум важным идеям:

  1. Это очень мощное средство для «непосредственного программирования», то есть указания компьютеру, что делать.

  2. Большая часть однострочника посвящена grep/awk/cut/tr, которые каким-то образом выковыривают и приводят в человеческий вид вывод предыдущих утилит.




При том, что модель pipe'ов восхитительна, совершенно грязные хаки по отлову нужных полей в выводе во втором пункте («а вот тут мы можем выделить нужное нам по характерной запятой с помощью awk -F, '{print $2}'...) делают процедуру спорной по удовольствию, и уж точно нечитаемой.

Ещё одна серьёзная проблема: при том, что шелл даёт довольно много идиом из функционального программирования, в нём нет идиомы фильтрации списка по результату выполнения внешней программы. То есть „грепнуть“ список мы можем. А вот оставить в списке только те элементы, для которых какая-то программа вернула „успех“ — нет.


При этом есть враждебная и не очень хорошо написанная среда — powershell (винды). В которых взяли хорошую идею (пайпы передают не текст, а объекты), но испортили её двумя вещами:



  1. Неэргономичной консолью виндов (Shift-PgUp где, а?)

  2. предложением пойти и выучить .net для того, чтобы нормально с методами работать.


Хочется иметь объекты в пайпе в тёплом ламповом линуксовом шелле. С hand-candy (мало печатать), eye-candy (приятно смотреть) и общей эргономичностью процесса использования. Ещё хочется иметь возможность сочетать „новый подход“ со старым, то есть обычным текстовым pipe'ом.




Надо написать набор инструментов, которые позволят в pipe-style оперировать с структурированными данными. Очевидным выбором является XML JSON.

Нам нужно:

  1. Утилиты, которые примут типовые форматы на вход и сконвертируют их в json.

  2. Утилиты, которые позволят в pipe'е манипулировать с json'ом.

  3. Утилиты, которые приведут json в „обычный“ формат.




В этом случае человек не будет видеть json на экране, но будет иметь возможность работать с ним.

(для понимания я буду писать длинные имена утилит, в реальной жизни это будут короткие сокращения, то есть не json-get-object, а что-то типа jgo или jg)

Выводит только файлы, для которых file сумел определить тип:

ls -la | ls2json | json-filter 'filename' --exec 'file {} >/dev/null' | json-print


Выкачивает с некоторого сайта токен для авторизации, выковыривает его из json'а и выставляет в переменные среды окружения, после чего скачивает список и отфильтровав по регэкспу поле „автор“ выкачивает все url'ы:

curl mysite/api.json | env `json-get-to-env X-AUTH-TOKEN`;curl -H X-AUTH-TOKEN $X-AUTH-TOKEN mysite/api/list.json | json-filter --field 'author' --rmatch 'R.{1,2}dal\d*' | json-get --field 'url' | xargs wget


Парсит вывод find -ls, сортирует по полю size, вырезает из массива элементы с 10 по 20, выводит их в csv.

find . -ls | ls2josn | json-sort --field 'size' | json-slice [10:20] | json2csv




input'ы




Основная задача — из messy-вывода сделать json-конфетку. Важно: иметь опцию для обработки некорректного ввода: а) игнорировать, б) останавливать pipe с ошибкой.

Примеры:

Generic:



  • line2json — конвертирует обычный вывод в массив строк, где строка соответствует строке (line to string).

  • words2json — аналогично, но по „словам“.

  • csv2json — конвертирует cvs в объект, позволяя указанный элемент назначить ключом.

  • lineparse2json — конвертирует строку в объект, разделяя её по указанным символам. Напоминает awk -F: '{print $1, $2}',


app-specific:



  • ls2json (на выбор — либо делает ls, либо берёт вывод ls) и структурирует его как массив объектов, где каждый объект — файл с кучей полей. Может быть, даже большей, чем умеет ls (обычные и расширенные атрибуты lsattr, вся информация про иноды, даты создания и т.д.)

  • ps2json — аналогично, по спискам процессов

  • lsof2json — список объектов, описывающих приложения, использующие файл.

  • openfiles2json — список fd, открытых приложением (/proc/PID/fd), с встроенной фильтрацией, например, „files only“, „ignore /dev/null“. В объектах по сетевым сокетам сразу же прилагается вся информация — порты/ip.

  • iptables2json — выводит текущие настройки iptables в форме json




File-specific:

Читают файл, выводят его в json'е.


  • syslog2json

  • ini2json

  • conf.d2json

  • sysv2json, upstart2json




нативные json-преобразования




Самое вкусное — нативные манипуляции над json'ом. Аналогично, должны иметь опции обработки „не json'а — “игнорировать»/«останавливаться».

  • json-filter — фильтрует объекты/массивы по заданным критериям.

  • json-join — делает из двух json'ов один указанным методом.

  • json-sort — сортирует массив объектов по указанному полю

  • json-slice — вырезает кусочек из массива

  • json-arr-get — возвращает элемент из массива

  • json-obj-get — возвращает заданное поле/поля указанного объекта

  • json-obj-add — добавляет объект

  • json-obj-del — удаляет объект

  • json-obj-to-arr — выводит ключи или заданное поле объектов как массив

  • json-arr-to-obj — превращает массив в объект формируя ключ по заданному признаку.

  • json-uniq — удаляет повторяющиеся элементы в массиве (или выводит только повторяющиеся)




(добавить по вкусу и потребностям)

output'ы




Приводят json в человекочитаемый вид:


  • json2fullpath — превращают json в нотацию строк вида key1.key2[3].key4 = «foobar»

  • json2csv

  • json2lines — выводят массив по элементу на строку, если внутри объекты — разделяя их пробелами на строке.

  • json2keys — выводит ключи объекта

  • json2values — выводит только значения объекта


iterator'ы




Фактически, расширение xargs на json:


  • json-keys-iterate — запускает указанные команды для каждого ключа

  • json-values-iterate — запускает указанные команды для каждого ключа

  • json-iterate — запускает указанные команды для каждого элемента




Разумеется, такими методами невозможно решить проблему обработки произвольного json'а — он может оказаться слишком «неструктурированным». Но во-первых input'ы делают таки предсказуемый вид json'а, а во-вторых, обработка json'а всё-таки более предсказуема, чем обработка «типа тут пробелами элементы разделяются» в существующем шелле.

Я бы сам написал, но часть нужного я не знаю, на что-то мне не хватает времени. Не программист, я. Тайной мыслью статьи является, что «кто-то напишет за меня», но если такого не найдётся, то останется хотя бы программная статья с мотивацией доучить(ся) и сделать самому.

Если кто-то готов за подобное взяться — буду крайне благодарен. Если нет, буду свой фиговый питон расчехлять — и идеи и предложения приветствуются.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий