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

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

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

При этом есть враждебная и не очень хорошо написанная среда — powershell (винды). В которых взяли хорошую идею (пайпы передают не текст, а объекты), но испортили её двумя вещами:
  1. Неэргономичной консолью виндов (Shift-PgUp где, а? говорят, Ctrl-PdUp в новых версиях)
  2. предложением пойти и выучить .net для того, чтобы нормально с методами работать.
  3. Отсутствием под большинство операционных систем


Хочется иметь объекты в пайпе в тёплом ламповом линуксовом шелле. С 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


Как подсказывают в привате, mysql-json отлично ложится на эту идею. Запускать бинарники по выводу из sql'я? Запросто.

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'а всё-таки более предсказуема, чем обработка «типа тут пробелами элементы разделяются» в существующем шелле.

Реализация


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

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

UPDATE: Вроде бы, люди чуть-чуть зашевелились. Вашим коммитам будут рады тут: github.com/amarao/json4shell. Когда это можно будет использовать — пока не знаю. Хватит ли пороха — тоже не знаю.

Комментарии (133)


  1. bak
    01.06.2014 09:54

    Однострочники на шеле — ад. Они хороши, когда по быстрому нужно сделать одно (несколько) простое действие с лёгкой логикой. Заниматься обработкой структурированных данных в однострочниках — плохая идея. Для этого можно открыть любимый REPL и сделать в нём всё тоже самое.


    1. amarao Автор
      01.06.2014 09:54

      Однострочники — это оригинальный смысл слова «программирование». То есть не отлитие в чугуне продакшен кода на века вечные. Однострочник, это чтобы сделать _сейчас_.

      Мне сейчас нужно получить список процессов, с которыми я там что-то сделать хочу.

      И «обработка» подразумевает _сейчас_. Чтобы получить ответ. Их смысл примерно такой же, как у формулы снизу таблицы в excel'е — это прямое указание компьютеру «поди и сделай». И это указание быстро пишется и быстро выполняется. Без длительных import, prelude, расписания модели классов и т.д.

      В каком-то смысле однострочник — это «программа» масштаба программы для программируемого калькулятора. Она делает только то, что надо делать и не делает ничего другого (в том числе того, что хотелось бы для упрощения отладки/сопровождения).

      Переиспользуемые однострочники — это уже спорный вопрос (если он переиспользуется — не переписать ли его как нормальную программу?). Но вот в режиме «ща посмотрю» или «ща сделаю» — у них просто нет альтернатив.


      1. Bal
        01.06.2014 09:54

        >И это указание быстро пишется и быстро выполняется. Без длительных import, prelude, расписания модели классов и т.д.

        То, что мир потерял с уходом Бейсика. И то, на чём в своё время Бейсик набрал популярность. Там программу можно было писать с первой же строчки.


        1. tyomitch
          01.06.2014 09:54

          Очень много скриптовых языков целятся в эту же нишу, от JS до Python


          1. ApeCoder
            01.06.2014 09:54

            И нескриптовых тоже, например, F#


    1. zencd
      01.06.2014 09:54

      С каких это пор несколько пайпов стали адом?


      1. bak
        01.06.2014 09:54

        Несколько пайпов — норм, я имел ввиду ситуации когда этими однострочниками начинают делать какие-то не тривиальные вещи, вроде парсинга html-я, json и т. п.


        1. amarao Автор
          01.06.2014 09:54

          Погодите. Мне не нравится future continuous у вас в словах.

          Если кому-то надо быстро выдрать из html'ки нужные данные и он их выдирает — никаких проблем. Кто быстрее, того и тапки.

          А вот если он его куда-нибудь стационарно прописывает «а вот тут мы по крону делаем вот такой трюк, и наш сайт объявлений работает» — то это уже совершенно другой разговор, и за такое (если это не прототип из г-на и палок) надо больно бить по рукам, за диверсию в отделе сопровождения.

          Пайпы и однострочники — это инструментарий системных администраторов и похожих на них пользователей. И у него масса проблем, но это проблемы «иногда неудобно», а альтернативой им является «никак нельзя за 5 минут это сделать».


          1. bak
            01.06.2014 09:54

            Задачки вроде взять список процессов и посчитать, сколько памяти съели некоторые из них — это одно. Для таких шел и пайпы — самый естественный способ. Задачка сходить по http за html-кой, вытащить из неё какие-либо данные, чёто с ними поделать, сформировать json-чик а затем положить в mysql — лучше всё же решать на скриптовых языках врод python/perl/etc.
            Когда находишь для себя новый прикольный инструмент — хочется начать решать им все задачи. В IT очень много тьюринг-полных штук, а значит почти любой инструмент можно заставить решать почти любую задачу, но это не всегда целесообразно.


            1. amarao Автор
              01.06.2014 09:54

              Предметная область не важна. Важно то, как оно используется. Если это однократная операция, то однострочник будет быстрее в разработке, чем любой другой вид программирования. Сам однострочник может быть и перловым, если кому-то привычнее.

              Это tradeoff между скоростью написания и удобством сопровождения. Если мы можем полностью пожертвовать сопровождением, то можем значительно выиграть в скорости написания.

              Если же получившийся код начинают сопровождать, что кратковременная экономия на времени написания оборачивается длинной попоболью в сопровождении.


  1. david_mz
    01.06.2014 09:54

    Вообще, идея очень хорошая.

    app-specific утилиты, наверное, стоит спрятать в одну утилиту-враппер: json-src ls -la, json-src ps ax и так далее. Под капотом у неё будут отдельные плагины для работы с конкретными командами в конкретных средах.

    (я бы на go писал:))


    1. amarao Автор
      01.06.2014 09:54

      Плагины меня смущают, потому что юникс-принцип — каждая утилита делает только одно дело, но очень хорошо. (На самом деле всем понятно, что это будет пачка симлинков на одну и ту же программу, но с точки зрения пользователя они должны выглядеть как разные программы).

      Если готовы осилить — будет вам искренняя благодарность. А go, то есть быстрые бинарники — так, вообще супер.


      1. powerman
        01.06.2014 09:54

        Предложенный подход лучше описанного в статье не потому, что плагины, а потому, что вывод команд очень сильно зависит от параметров. Поэтому написать утилиту ps2json вызываемую в конвейере после ps будет намного сложнее, чем утилиту которая сама вызывает ps, зная с какими параметрами она его вызывает и в каком формате ей ожидать результаты.


        1. amarao Автор
          01.06.2014 09:54

          В соседнем треде обсудили и решили, что лучше иметь jps, jls и т.д., из-за проблем с парсингом. В принципе, это не отменяет input'ов от произвольных утилит, но json-версии для генерирующих coreutils/procutils — надо. (ls, find, ps, free, who, last, df, du, etc)


          1. powerman
            01.06.2014 09:54

            Ну, учитывая что вариантов разных реализаций ls/ps полно, и чем делать парсинг их вывода (со всеми возможными вариантами и самих утилит и их ключей) проще повторно реализовать их функциональность в рамках jls/jps — мы приходим к тому, что нужен не парсер из pipe в json, а отдельные «командлеты» как в powershell. Далее, если мы захотим чтобы эти новые команды были совместимы по параметрам со своими базовыми командами, выяснится, что как минимум половина параметров стандартных команд отвечает за то, какие данные выводить и как их форматировать — что при выводе в json теряет смысл т.к. проще сразу вывести все возможные данные (а для отбора нужных полей, сортировки, группировки и финального форматирования удобнее будет использовать специальные json-утилиты).


            1. amarao Автор
              01.06.2014 09:54

              Тут не должно быть противопоставления. jls/jps и остальное, что захотите, да. Но при этом они являются лишь простейшими утилитами, которые не являются частью systemd гигантского монстрообразного фреймворка. Если спросить, что делает jls, ответ будет — выводит список файлов в json'е. Без каких-либо фреймворков, командлетов чего-либо.

              То есть я старательно любуюсь идеей самостоятельных утилит, каждая из которых делает одно, но хорошо, а вы меня пытаетесь убедить, что это то же самое, что команды в гигантском фреймворке, построенном на совершенно необъятном титаническом гига-мега-фреймворке. А я вам не верю.


              1. powerman
                01.06.2014 09:54

                Ну, не то, чтобы действительно пытаюсь. На самом деле у меня крайне поверхностное представление о PowerShell и командлетах, сам я им не пользовался, только читал про него и смотрел примеры. И мне не понравилось. Ну т.е. это реально лучше стандартной виндовой командной строки, но по-моему зря они через пайпы решили гонять объекты — это слишком сложно и наворочено. Так что я не пытаюсь Вас убедить, я просто высказываю относительно обоснованное опасение, что двигаясь в эту сторону Вы можете прийти к чему-то вроде PowerShell, со всеми его недостатками в виде использования своих собственных команд вместо штатных утилит и довольно сложными операциями над (так же довольно сложными) данными передаваемыми через конвейеры. И необходимостью знать все эти новые команды и данные чтобы им пользоваться.


                1. ApeCoder
                  01.06.2014 09:54

                  Powershell может использовать штатные утилиты (см ниже пример с Grep). Объекты это проще для использования, потому, что не надо ни на передающей стороне ни на принимающей определять формат данных — есть уже готовое соглашение. И перечень свойства тоже не обязательно явно указывать, если его не надо выводить.

                  пример (вывод 10 последних созданных файлов в CSV):

                  ls | sort CreationTime -Descending | select -First 10 | epcsv c:\test.csv

                  ls по умолчанию вообще не выводит CreationTime, но, тем не менее, я могу использовать это свойство. Мне никак не надо заботиться о формате данных (объяснять ls, что нужно дальше по пайпу).


                  1. powerman
                    01.06.2014 09:54

                    Не самый удачный пример — когда сравниваешь это с ls -t | head как-то не возникает восхищения объектами в пайпах.


                    1. ApeCoder
                      01.06.2014 09:54

                      восхищения не возникает из за захардкоженности сортировки в ls или из за того, что вывод в csv проигнорирован? :)


                      1. powerman
                        01.06.2014 09:54

                        Вы не поверите, но… ни разу за 20 лет работы в командной строке линуха мне не требовалось сохранять результат конвейера в csv. Поэтому и проигнорирован.


                      1. ApeCoder
                        01.06.2014 09:54

                        А мне периодически это бывает удобно. Как бы вы сделали такое на вашем шелле?


                      1. powerman
                        01.06.2014 09:54

                        Ну, с учётом того, что мне это никогда не было нужно, и я не знаю существующих утилит которые бы это делали, то я бы это сделал в лоб ручками (для примера создадим файл с именем, которое нужно экранировать в csv):

                        touch 'a  ,  b  "  c'
                        ls -ltQ | head -n 6 | tail -n 5 |
                          perl -pe '$_=join",",split" ",$_,9;s/\\"/""/g'
                        
                        -rw-r--r--,1,powerman,powerman,0,июн,2,18:21,"a  ,  b  ""  c"
                        drwx------,3,powerman,powerman,4096,июн,2,17:53,"Mail"
                        drwxr-xr-x,12,powerman,powerman,4096,июн,2,17:44,"download"
                        drwx------,9,powerman,powerman,4096,июн,2,07:09,"doc"
                        drwxr-xr-x,18,powerman,powerman,4096,май,30,14:21,"tmp"
                        
                        Наверняка существуют утилиты (или хотя бы модули для перла) использование которых сделало бы эту команду короче и читабельнее. Но в ситуации когда один раз за 20 лет понадобилось вывести список файлов в csv — сойдёт и такое.


                      1. ApeCoder
                        01.06.2014 09:54

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

                        Ну как бы оно не было сделано, пока нет четкого соглашения о форматах надо каждый раз раскорячиваться — разбирать и собирать и для интересных колонок определять формат. Либо нагружать каждую конкретную команду еще и командами обработки — как например ls содержит себе sort, но только по выделенным атрибутам.


                    1. amarao Автор
                      01.06.2014 09:54

                      А теперь попробуйте вырезать из этого файлы с 5 по 10 и вывести только пару файл — атрибуты.


                      1. powerman
                        01.06.2014 09:54

                        Не совсем понимаю, что это покажет, и о каких конкретно атрибутах речь, но в любом случае это не проблема:

                        ls -t | head | tail -n 5 | xargs -i stat -c '%A %n' {}
                        
                        -rw------- mbox3
                        -rw------- mbox2
                        -rw------- mbox1
                        -rw------- postponed
                        drwxr-xr-x VirtualBox VMs
                        


                      1. amarao Автор
                        01.06.2014 09:54

                        Добавьте символы табуляции и перевода строки к имени файла и повторите тест.


                      1. powerman
                        01.06.2014 09:54

                        А вот честно, лично Вам хоть раз в жизни попадались эти символы в именах файлов? Кроме того, баги есть абсолютно в любом софте, почему в этом онлайнере их не должно быть вообще?


                      1. amarao Автор
                        01.06.2014 09:54

                        Табы и пробелы — постоянно. А ещё япоцы любят в неюникодных архивах отжечь по-чёрному с именами файлов.


                      1. powerman
                        01.06.2014 09:54

                        Никогда не встречал табов в именах файлов (кроме тех случаев, когда сам их вставлял для тестирования). Как они туда вообще попадают? В командной строке никто такое делать в здравом уме не будет. В гуи таб обычно при всём желании в имя файла не вставишь т.к. нажатие таб переключит фокус с поля ввода имени файла на следующий контрол. Так откуда в именах Ваших файлов табы?


                      1. amarao Автор
                        01.06.2014 09:54

                        Распаковал архив.


  1. vaniaPooh
    01.06.2014 09:54

    Проблема JSON в том, что нет нормального стандарта по его валидации. Есть несколько подходов к валидации наподобие json-schema.org/, но они не являются официально одобренными стандартами, а, значит, не выглядят совсем «серьезными», как, например, XSD или XSLT. С другой стороны XML не так удобен, если им оперировать в одну строчку. Но как насчет такой связки: утилита | инструмент генератор XML | xsltproc? Можно написать набор XSL преобразований, которые реализуют те же возможности, что и предлагаемые вами.


    1. amarao Автор
      01.06.2014 09:54

      То есть вы предлагаете пользователю писать xsl? Просто для осознания масштаба проблемы: мне надо взять список из одного места, отфильтровать его, взять одно поле из оставшегося, и к этому применить программу.

      Сколько сотен кнопок надо будет посвятить злому божеству XML, чтобы это описать на XSL? Вопрос исключительно и только в эргономике.

      Валидацию json'а можно делать методом «не грузится в используемую библиотеку». CS-фрики будут плакать, остальных это устроит.


      1. Sauron
        01.06.2014 09:54

        По сути вы говорите о аналоге XSL для JSON, вот вам и пишут что недостаток JSON-а в том, что нет для него XSL и даже XPATH. Был бы хоть XPATH для JSON — не было б проблем.

        P.S. Кстати, всякие самописные JSONPath существуют — goessner.net/articles/JsonPath/
        Может ваша задача решается запуском JSONPath из консоли? Для того, чтоб «отфильтровать список» (т.е. выбрать элементы, соответствующие сложному условию) — самое оно. И «взять одно поле из оставшегося» — аналогично.


        1. amarao Автор
          01.06.2014 09:54

          Мы смотрим на это с разных точек зрения. Вы с точки зрения «стационарного программиста». Который код пишет меньше, чем этот код потом работает. В таком случае написание преобразования вполне оправдано.

          Я же говорю про стыкуемость деталек для одноразового калейдоскопа. Если там хотя бы штук 50-80 кнопок на преобразование, это мертворождённый проект. Вне зависимости от архитектурной красоты.

          Возможно, я не до конца понимаю, как xsl будет выглядеть, если покажете общественности, буду благодарен.

          На входе — xml с именованными полями для каждого объекта в перечислении, надо по полю «name» отфильтровать тех, кто foo.+bar, а потом вывести только поле «display».


          1. Sauron
            01.06.2014 09:54

            Для вашего случая достаточно одного XPath выражения — это гораздо короче чем полноценная XSLT.

            Опять же, смотрите в сторону JSONPath (выше по ссылке примеры результатов есть) и возможности запустить его из терминала.

            Я вот какраз нагуглил и пытаюсь запустить такое — search.cpan.org/~sharyanto/App-jpath-0.03/bin/jpath


          1. Sauron
            01.06.2014 09:54

            Вроде пошло.
            Я не понимаю ничего в Перле, но вроде как:
            cpan App::jpath
            инсталирует jpath как комманд-лайновую утилиту.

            А дальше все просто:
            cat test.json | jpath "$.store.book..title"

            Для такого test.json:

            test.json
            { "store": {
                "book": [
                  { "category": "reference",
                    "author": "Nigel Rees",
                    "title": "Sayings of the Century",
                    "price": 8.95
                  },
                  { "category": "fiction",
                    "author": "Evelyn Waugh",
                    "title": "Sword of Honour",
                    "price": 12.99
                  },
                  { "category": "fiction",
                    "author": "Herman Melville",
                    "title": "Moby Dick",
                    "isbn": "0-553-21311-3",
                    "price": 8.99
                  },
                  { "category": "fiction",
                    "author": "J. R. R. Tolkien",
                    "title": "The Lord of the Rings",
                    "isbn": "0-395-19395-8",
                    "price": 22.99
                  }
                ],
                "bicycle": {
                  "color": "red",
                  "price": 19.95
                }
              }
            }



            Возвращает названия книжек. Правда в формате JSON массива тоже.
            [
               "Sayings of the Century",
               "Sword of Honour",
               "Moby Dick",
               "The Lord of the Rings"
            ]


            1. amarao Автор
              01.06.2014 09:54

              А греп в середине?


              1. Sauron
                01.06.2014 09:54

                Должно работать с условиями, там в примерах есть:
                $..book[?(@.price<10)]
                Выбор всех книжек дешевле 10.

                Правда в той версии которую мне поставил cpan это почему-то валится с ошибкой. Но видимо надо просто как-то скомпилить новую из сорсов с github.

                Почитайте про XPath и условия в нем. Здесь все должно быть аналогично.

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


                1. amarao Автор
                  01.06.2014 09:54

                  Да, выглядит терпимо. Но я xpath не очень люблю, хотя, json-версия может быть полезна. В принципе, в рамках описываемой модели, как один из инструментов (для тех, кому надо и не лениво) — why not?


                  1. int19h
                    01.06.2014 09:54

                    Посмотрите еще на XQuery. Там вообще полный turing complete с весьма навернутыми запросами а ля SQL — группировки, окна, вот это все.

                    Единственный недостаток — длинноватый синтаксис для «повышенной читабельности». Но при этом куда более лаконичный XPath является чистым subset, поэтому можно пользоваться в основном им, а FLWOR оставить для сильно навернутых запросов, где эта читабельность реально имеет смысл.

                    С другой стороны, сам XML как формат явно избыточнен для таких целей, а вот JSON — самое оно.


        1. vaniaPooh
          01.06.2014 09:54

          Я скорее имел в виду наделать готовых XSL-файлов и распространять в виде библиотеки.


          1. Sauron
            01.06.2014 09:54

            Ага. Ну свои выражения писать — полюбому гибче будет.


            1. amarao Автор
              01.06.2014 09:54

              Как несколько утилит (j2x для конвертации в xml, x2j обратно, и что-то посредине) — почему бы и нет? Основные тезисы: пользователь не должен видеть потрохи. xml там, json или что-то ещё — не важно. Пользователь данные всунул, написал/использовал логичный фильтр (логику которого можно понять без взгляда на xml), пользователь получил данные.


              1. vaniaPooh
                01.06.2014 09:54

                Да, конечно.


  1. zserge
    01.06.2014 09:54

    Можете посмотреть на jq — stedolan.github.io/jq/
    Какую-то малую часть задач по обработке JSON он решает.


    1. amarao Автор
      01.06.2014 09:54

      Да, я его видел. К сожалению, не полностью то, что нужно.


    1. Self_Perfection
      01.06.2014 09:54

      Добавлю, что json-get уже есть и называется jshon.


      1. amarao Автор
        01.06.2014 09:54

        Спасибо, посмотрю.


  1. Mox
    01.06.2014 09:54

    Идея хорошая, но вот json — он все таки не «потоковый» формат, может быть yml здесь подолшел бы лучше? С другой стороны — если операции над json объектом, то может быть не получив объект целиком нельзя им оперировать?


    1. amarao Автор
      01.06.2014 09:54

      grep тоже не потоковый. Ему хочется строчку целиком, а не поток байтов. Однако, для практических целей это не важно (а более злую буфферизацию приходится отключать с помощью --line-buffered).

      Я думаю, имея на руках объект верхнего уровня, легко понять что ждать дальше. Если это object, то ждём следующего key+value, если это array, то элемента.

      Хотя да, вопрос интересный. Потоковость туда придётся утрамбовывать силком.


      1. zibada
        01.06.2014 09:54

        Зачем на верхнем уровне все запихивать в один array?
        Общепринятный формат вывода многих юниксовых утилит — «одна строка — один объект».
        Его и стоит придерживаться, только формат отдельных строк сделать json вместо каши из произвольных разделителей.
        То есть, выводить список объектов по одному на строке, разделять \n, заканчивать EOF, \n в значениях полей эскейпить.

        Бонусы:
        1. Итерация по строкам тривиально реализуется во всех языках программирования, без специальных json-парсеров
        2. Стандартные head, tail, uniq и прочие работают из коробки как надо, даже не зная, что в строках json
        3. Человекочитаемо даже без специального pretty-print
        4. Это никак не ограничивает возможность создания вложенных списков или принудительного представления вывода одним array, если ну очень хочется.


        1. amarao Автор
          01.06.2014 09:54

          То есть вы предлагаете использовать стопку json'ов вместо одного ч массивом? Спасибо за идею, буду думать/сравнивать.


          1. Lamaster
            01.06.2014 09:54

            Согласен с zibada. Т.к команды в шелле при использовании пайпов запускаются параллельно, они между собой передают по одной строке, содержащей JSON. Это позволяет не напрягать одну команду в один момент времени всем результатом, а прогонять «по-объектово».


    1. ApeCoder
      01.06.2014 09:54

      Чем YAML более потоковый чем JSON?


      1. powerman
        01.06.2014 09:54

        Вероятно имелось в виду, что в большинстве случаев данные в YAML будут содержать по одному значению в одной строке и без всяких скобочек открывающих/закрывающих списки и объекты — что может дать возможность удобно обрабатывать его даже стандартными утилитами grep/sed/etc… Но на практике YAML значительно сложнее JSON, и там есть и свои многострочные значения, и скобочки.

        Впрочем, с ходу я бы эту идею отметать тоже не стал — ведь в большинстве случаев YAML таки будет простым, и обработка его стандартными grep/sed/etc. будет подвержена ошибкам из-за не учтённых нюансов в формате входных данных не более, чем она подвержена этому сейчас, когда парсит вывод ps/ls напрямую.


  1. ApeCoder
    01.06.2014 09:54

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

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

    Можно ли узнать что делает эта комбинация? По быстрому не смог найти.

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

    Я так понял, что при использовании json нельзя вообще вызывать методы так как передаются только данные без поведения. Можно ли узнать чем json лучше в этом аспекте Powershell.

    В предыдущих спорах по поводу шеллов мне говорили что уже есть объектный шелл — ipython — рассматривали ли вы его?


    1. amarao Автор
      01.06.2014 09:54

      Shift-PgUp/Dn мотает консоль на экран вверх/вниз. Быстрый метод увидеть history за пределами экрана. В виндах для этого приходится тянуться к мышке. (Приходилось по состоянию на 2008 год, как сейчас — не знаю).

      json в этом случае проще. То есть охватываемо и изучаемо. .net для целей системного администрирования — это примерно как «эрланг для целей написания конфигов», то есть смещение POV с удобства пользователей на удобство разработчиков системы.

      ipython я юзаю, к сожалению, там такого сделать нельзя:
      In [5]: for a in `ls /`:
      ...: print a
      ...:
      File "<ipython-input-5-a746a2e08210>", line 1
      for a in `ls /`:
      ^
      SyntaxError: invalid syntax

      То есть совместить удобно шелл и обработку данных не получается. Если бы было можно — было бы здорово.


      1. ApeCoder
        01.06.2014 09:54

        В powershell ISE это комбинация Ctrl + PgUp

        «json в этом случае проще» в powershell можно ограничиться изучением свойств, а методы не учить. Весь дотнет можно не учить — только то, что требуется в данный момент. То есть эта сложность получится по требованию.

        ipy я не юзаю, но суда по карточке, там можно это сделать, но системный команды предвараются!
        damontallen.github.io/IPython-quick-ref-sheets/
        типа files = !ls /usr


        1. amarao Автор
          01.06.2014 09:54

          Ага, значит, что-то прикрутили.

          Вариант «вечно доучивать» меня не устраивает. Да и как жить с внешним миром не понятно — power she'll на себе замкнут, с выводом из перлового скрипта и отправкой в awk его штатно не заюзать. Или, там, с grep'ом посреди pipe'а.


          1. Lol4t0
            01.06.2014 09:54

            Так работает ls | grep ".exe" | echo

            ls и echo — alias-ы ps, grep — из msys


            1. amarao Автор
              01.06.2014 09:54

              Ок, мне надо взять список открытых fd из /proc. Как мне это сделать? Допустим, центось. Или дебиан.


              1. ApeCoder
                01.06.2014 09:54

                Это уже совершенно другая претензия — Powershell есть только на винде.

                Можно попробовать sourceforge.net/projects/pash/ но я бы не стал :)


                1. amarao Автор
                  01.06.2014 09:54

                  То есть если бы оно было кросс-платформенное (и не такое адское, как mono), то я бы его ещё мог рассматривать. Но я с трудом себе представляю боевой сервер, на котором ставят mono только ради пайпов в шелле у админа.


          1. ApeCoder
            01.06.2014 09:54

            >>Вариант «вечно доучивать» меня не устраивает.

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

            >>Или, там, с grep'ом посреди pipe'а

            Это еще почему?

            Get-ChildItem | grep exe | ogv

            Вполне работает. Только grep принимает и выдает строчки => объектов вы не увидите на последнем конце. Ну так он и json так же может испортить. (Можно в принципе написать чуть сложнее, с использованием Where-Obkect — чтобы объекты доезжали до конца)

            Единственный недостаток который я встречал, это если в ps1 включать обычный консольные команды, а потом весь вывод редиректить — тогда все падало (не уверен, что не исправили)


            1. amarao Автор
              01.06.2014 09:54

              Ок, перейдем к главному. Apt-get install что?


              1. dimitrimus
                01.06.2014 09:54

                только make && make install, только хардкор


                1. amarao Автор
                  01.06.2014 09:54

                  ок, лёгким движением dh_make make install превращается в dpkg -i. Где оный make & make install под юниксы найти? (там ещё ./configure в комплекте, да?)


                  1. dimitrimus
                    01.06.2014 09:54

                    не специалист по юниксу, но там что, нет make? на макоси как и на линуксе есть, к примеру


                    1. amarao Автор
                      01.06.2014 09:54

                      make есть. Сырцов, которые бы правильно ./configure нет.


                      1. kekekeks
                        01.06.2014 09:54

                        Если вам нужно из MSBuild сделать autotools-скрипты (я обычно пользуюсь xbuild и парой доп. команд в debian/rules для того чтобы скопипровать бинарники в нужные директории), можно воспользоваться monodevelop. Ещё есть пакет cli-common со скриптами для debhelper, прописывающий нужные зависимости и устанавливающий нужные сборки в GAC. Процесс сборки пакетов несколько отличается от стандартного для сишки, что не удивительно, с явой примерно так же.


                      1. amarao Автор
                        01.06.2014 09:54

                        Вот мы и пришли к главному — mono снизу. Гигантский, неподъёмный, который никто на сервер просто так не пустит (ради мелких cli-утилит).

                        Плюс полная несовместимость ни с кем, кроме себя (я ниже писал про разницу между «умный шелл» и «простые утилиты через pipe»).

                        Условно говоря, вывод curl'а «как есть с js'ом» в powershell не загонишь, и «похакать sed'ом посредине json'а» тоже непохакаешь.

                        Фреймворк слишком объёмный и претендующий на среду исполнения. А это означает, что все, кто не с этой средой — в пролёте.

                        То есть просто прямой анти-юникс.


              1. ApeCoder
                01.06.2014 09:54

                Что именно вы имеете ввиду?
                Если отсутствие packange managers, то есть 3rd party: chocolatey.org/
                и на этапе CTP находится OneGet github.com/OneGet/oneget/wiki/cmdlets

                Если то, что PoSh не работает под юниксом, то так сразу бы и сказали :)


      1. dsx
        01.06.2014 09:54

        Начните свой день в iPython с «import sh» (https://pypi.python.org/pypi/sh). Делает именно то, что вы хотите, только на питоне: «for a in ls('/'): [...]».


        1. amarao Автор
          01.06.2014 09:54

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


          1. dsx
            01.06.2014 09:54

            Фантастика на другом этаже. Все юниксовые шеллы — это интерпретаторы языков программирования, от которых сильно зависит запустится ваш однострочник или нет, не говоря уже о корректной работе. Попробуйте сделать одно и то же в bash и csh. Или даже в близкородственных zsh и bash. Разница есть, и не всегда очевидная (как во втором случае). Выбор состоит в том, от какого языка вам выгоднее зависеть.


            1. amarao Автор
              01.06.2014 09:54

              Погодите, погодите. У разных шеллов разный синтаксис своих команд. Но модель pipe'ов у всех одна и та же. Я хочу иметь набор инструментов, которые бы не были завязаны на конкретный язык. Большинство же советующих «сделать такой шелл» (или рассказывающих о том, какой крутой powershell) просто этого не чувствуют. Для них, если один шелл умеет, этого достаточно. А я хочу научить все шеллы этому. Все. От бизибоксового sh до fish'а.


              1. dsx
                01.06.2014 09:54

                Пайп — это такой же языковой примитив, как и for или if. То, что он конвенционно везде одинаково выглядит не гарантирует того, что он везде одинаковый и даже будет одинаково работать. Перенаправлять потоки ввода-вывода можно и без пайпов, используя файловые дескрипторы и «шевроны» (>).


                1. amarao Автор
                  01.06.2014 09:54

                  Да. Но среди всех примитивов, pipe и fd — самые живучие и присутствующие во всех операционках с момента победы юникса. Даже в виндах pipe ведёт себя так же, как и в юниксе.

                  Какой значок будет использоваться в конкретном шелле не важно. Предложенная реализация будет работать с любыми значками перенаправления. Она зависит только от стыкования stdin одной программы в stdout другой.


                  1. dsx
                    01.06.2014 09:54

                    Тогда вам нужно соблюдать три правила: получать данные через стандартный ввод, выдавать результат в стандартный вывод и сообщать об ошибках в стандартный вывод ошибок. С остальным разберутся за вас.


                    1. amarao Автор
                      01.06.2014 09:54

                      Ну да. К этому я хочу добавить утилиты, которые будут принимать и отдавать json.


    1. Lol4t0
      01.06.2014 09:54

      Добавлю, что большинство проблема эргономики на Windows решаются использованием нестандартного терминала, ConEmu, например.


  1. kekekeks
    01.06.2014 09:54

    Мне кажется, или вы пытаетесь изобрести PowerShell?


    1. amarao Автор
      01.06.2014 09:54

      Во-первых я про него в посте написал, а во-вторых, я пытаюсь его сделать удобным и не завязанным на конкретный язык/среду исполнения.


    1. int19h
      01.06.2014 09:54

      Я бы скорее сказал, это попытка прикрутить «объектность» к существующему юниксовому пайплайну, не трогая существующие наработки в нем (в отличие от PS, который замещает собой большую часть досовых команд).

      И, кстати, более грамотная попытка, имхо. В PS мне активно не нравится то, что в пайпах там именно объекты — т.е. сущности с поведением. Имхо, это противоречит самой концепции «трубы», через которую льются данные, а поведение предоставляют программы с той и с другой стороны.


      1. ApeCoder
        01.06.2014 09:54

        А почему объединение данных и поведения это плохо? Это позволяет выделять общие абстракции не меняя данных.

        Пример:

        в powershell объектах могут быть вычислимые свойства которые позволяют обрабатывать все объекты одинкаово:

        ls | gm | ?{ $_.Name -match '^PS'}
        Name MemberType Definition
        — — —
        PSChildName NoteProperty System.String PSChildName=@OpenWithToastLogo.png
        PSDrive NoteProperty System.Management.Automation.PSDriveInfo PSDrive=C
        PSIsContainer NoteProperty System.Boolean PSIsContainer=False
        PSParentPath NoteProperty System.String PSParentPath=Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS\system32
        PSPath NoteProperty System.String PSPath=Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS\system32\@OpenWithToastLogo.png
        PSProvider NoteProperty System.Management.Automation.ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem

        И почему объекты нарушают концепию пайпа а не расширяют ее?


        1. int19h
          01.06.2014 09:54

          В вашем примере, Name — это как раз данные. Поведение — это методы вроде CopyTo.

          Объекты нарушают не столько саму концепцию пайпа, а концепцию шелла в целом. Поведение, обработка данных — это команды. Передача данных от команды к команде — это пайпы. Когда у вас объекты в пайпах начинают нести свое собственное поведение, вся система становится размытой, и непонятно, где именно искать нужное поведение. Например, в чем разница в PS между copy-item и CopyTo()? И почему вообще они существуют как две отдельные сущности с разным поведением?


          1. ApeCoder
            01.06.2014 09:54

            CopyTo это специфичный для файлов способ копирования 1 файла унаследованный из .NET, Copy-Item это копирование общее для powershell причем оно может выполняться как групповая операция. Достаточно посмотреть на набор параметров, чтобы понять разницу.

            Фактически это операции с разными сущностями — CopyTo копирует файл, Copy-Item копирует набор элементов. Просто может быть набор из одного элемента, и этот элемент — файл.


            1. int19h
              01.06.2014 09:54

              Ну вот и возникает вопрос — а почему, собственно, copy-item — это не метод на коллекции элементов, раз уж у нас есть методы? По какой логике разделять функционал на коммандлеты и методы, и где его искать в каждом конкретном случае?

              (копирование в данном случае — это просто пример, аналогичный вопрос можно задать про любую операцию)


              1. ApeCoder
                01.06.2014 09:54

                1. С точки зрения чистого разума, да в принципе можно было бы создать чистообъектный шелл чтобы любая команда была методом чего-то. Например сейчас copy частично дублирует функионал ls (выборка айтоемов по маске), но наверное, пошли на поводу у привычек. Объектно-логичнее было бы сделать вместо cp *.txt c:\x что-то типа (ls *.txt).cp c:\x или, если придумать какие-нибудь литералы для масок: *.txt | cp x

                2. Собственно методы обычно не являются функционалом шелла и наследуются от дотнет. Фактически у нас есть мультипарадигмальность: используй команды, специально написанные для шелла, если их не хватает у тебя есть настощие объекты дотнет


                1. int19h
                  01.06.2014 09:54

                  Да, и при таком подходе и пайпы не нужны тоже (точнее, они становятся синтаксическим сахаром для передачи параметров, как |> в F#).

                  Но это уже совсем другая история, которая к традиционному юниксовому шеллу имеет мало отношения.


                  1. ApeCoder
                    01.06.2014 09:54

                    ну собственно пайп и есть синтаксических сахар для передачи парметров — просто этот параметр — имеет строго один тип — текстовая строка (куда надо рендерить внутриенние объекты, потом опять парсить, потом опять рендарить и т.д)


          1. ApeCoder
            01.06.2014 09:54

            А, например, ScriptProperty это данные или поведение?

            BaseName ScriptProperty System.Object BaseName {get=if ($this.Extension.Length -gt 0){$this.Name.Remove($this.Name.Length — $this.Extension.Length)}els…
            VersionInfo ScriptProperty System.Object VersionInfo {get=[System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName);}


            1. int19h
              01.06.2014 09:54

              Если они являются чистой фунцкией от других свойств объекта — то данные (причем те же самые, просто другое их представление).


              1. ApeCoder
                01.06.2014 09:54

                VersionInfo является чистой функцией от других свойств (ему надо слазит в файл и посмотреть на версию)
                Если такие (вычисляемые по использованию) данные приемлемы, то как назвать совокупность этих вычислений и невычислемых данных? Я бы назвал объектом.


  1. CRImier
    01.06.2014 09:54

    Здравствуйте! Отличная идея. Сам иногда встречаюсь с необходимостью сделать однострочник, но вот отсутствие фильтрации, ВНЕЗАПНАЯ необходимость экранирования в самый неподходящий момент и порой наблюдающиеся проблемы с тем же sed — немного так бесят. Если собираетесь что-то писать, я с Вами — пишу на Python и буду рад помочь =)
    Кстати, ls2json не сможет нормально распарсить вывод ls. Почему — написано здесь. Поэтому — os.listdir(".") и что-то из похожего для дополнительной инфы =)


    1. amarao Автор
      01.06.2014 09:54

      Значит, jls, который понимает все осмысленные для json-вывода ключи.


  1. Gaen
    01.06.2014 09:54

    Я для себя решил проблему виндовой консоли через установку гита в режиме separate shell и GnuWin32.
    Первое дает полноценный bash-интерпретатор с поддержкой базовых команд типа ls, второе — полный набор программ типа grep, curl, wget итд.

    image


    1. amarao Автор
      01.06.2014 09:54

      Ну, тут проблема не как «на винды приличный шелл прикрутить», а как «сделать объекты в обычном пайпе без привязки к фреймворку/среде/ОС»


    1. StreetStrider
      01.06.2014 09:54

      Добавьте к этому комплекту ConEmu, не пожалеете.


  1. zencd
    01.06.2014 09:54

    Мне не нравится идея учить старого пса (sh) новым трюкам (объектам), гонять данные из безформатья в джейсон и обратно. Опять же базовые утилиты вроде «ls» изначально нездоровы в контексте обмена данными, как было замечено выше. По-мне так эту актуальную проблему способен решить красиво только собственный ОО-шелл, но тогда это уже будет аналог PowerShell'а, которого вы так избегаете. Впрочем, не отговариваю.


    1. amarao Автор
      01.06.2014 09:54

      Стоп. Где тут виден sh? Нет никакого sh. Есть pipe. Который действует по простым принципам:

      1. Прочитанное из одного stdout передаётся в другой stdin
      2. Передача прекращается, если одна из сторон закрывает pipe.
      3. Stderr идёт параллельно.

      Сам sh ни сном ни духом про формат того, что передаёт.

      ls относится к coreutils (tr/cut/sort/cat), а к ним у меня очень мало претензии и очень много любви. Судя по обсуждению выше, для ls и многих других coreutils, работающих с внешними данными, придётся сделать свои аналоги для крутой работы.

      Делать это _внутри_шелла_ — это как раз виндузятниковая модель (которой многие линуксы начали тоже страдать). Если это делается _внутри_ шелла, то использовать его вне этого шелла невозможно или неудобно.

      Если же оно делается автономно-независимо, с простейшими соглашениями по входу/выходу, то их можно будет использовать _и_ в понтовом oo-шелле, и busybox'е, имитирующем sh+coreutils, и ещё где-то, где его не ожидают.

      Собственно, я этой идеей загорелся, когда осознал, как она легко ложится на старую модель (и ни в одном месте ей не противоречит), и как легко её развивать в удобном направлении.


  1. tyderh
    01.06.2014 09:54

    Даю скромный диванный прогноз: не взлетит. Просто потому, что оно не нужно.

    Шелл хорош тем, что он убийственно прост, отчего им очень удобно решать простые задачи.

    Усложнять же его смысла нет никакого: для более сложных задач уже есть удобные инструменты. От Python до любого другого языка программирования.


    1. amarao Автор
      01.06.2014 09:54

      Именно этого я боюсь и хочу избежать. Чтобы человеку надо было что-то много и круто учить. Я предполагаю, что json в общем и целом все знают на уровне «примерно понимать о чём это». А дальше порог вхождения простой:

      jsplit file | jget [3] | xargs (дальше обычный шелл).

      Или

      jgrep foo *|jiterate -each echo file ${FILENAME} at line ${LINE} match ${MATCH}

      То есть я точно не хочу делать штуку, мануал к которой начнётся с знакомства человеков с ещё одним языком программирования и фреймворком.

      Условно говоря, если для применения первых 10 полезных фич надо будет прочитать больше 10-15 строк, значит это плохой старт.


  1. jackz
    01.06.2014 09:54

    На днях пробегала тут шикарная штука (правда, больше для питонистов, но все же): Pyp (Python Power at the Prompt).

    Вот замечательное видео как оно работает.

    Ну и сразу наглядный пример:

    \> ls | pyp "p[0] | pp.sort() | p + ' first letter, sorted!'" #gives sorted list of first letters of every line
    


    1. andgein
      01.06.2014 09:54

      Да это же настоящий perl -nle!


    1. amarao Автор
      01.06.2014 09:54

      Спасибо, интересно. Хотя не совсем то.


  1. symbix
    01.06.2014 09:54

    А может, лучше так — json ls, json find...? ну и симлики вида jls. Как в бизибоксе. Тогда и расширять проще, и внутренние реализации можно сделать для оптимизации или тех случаев, когда вывод стандартных команд сложно однозначно распарсить.


    1. amarao Автор
      01.06.2014 09:54

      Именно так. Но для простоты понимания в тексте полные имена приводятся.


  1. santeri
    01.06.2014 09:54

    tclsh?


    1. amarao Автор
      01.06.2014 09:54

      Примеры работы с структурированными данными?


  1. StreetStrider
    01.06.2014 09:54

    У меня была похожая, если не в точности такая же идея. Я постоянно работаю с JS и хотел применить похожие идиомы к обработке данных в пайпе (filter, map, проекции/выборки). Также на идею таких утилит меня натолкнул просмотр одной из презентаций Рича Хикки, где он много рассказывал языковые средства и их аналоги в среде командной строки.

    Правда я не думал, что такие утилиты будут кому-то полезными, к тому же операции разбора/вывода JSON будут весьма дороги (а их потребуется делать часто).
    Ещё я думал о том, как было бы клёво, еслиб все утилиты поддерживали опцию --json, которая любой их вывод приводила бы к некоторому JSON. Далее этот вывод поступает непосредственно на утилиты для работы с JSON.


    1. int19h
      01.06.2014 09:54

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


  1. StreetStrider
    01.06.2014 09:54

    А, совсем забыл. Есть похожая идея с SQL.
    github.com/dinedal/textql


  1. cebka
    01.06.2014 09:54

    В FreeBSD в этом году есть такой GSoC проект — machine readable output для всех утилит в базе. Человек, работающий над ним, пока смотрит в сторону yajl, который умеет выводить json потоково, но я, наверное, добавлю подобное в своем libucl, и мы будем использовать для этой задачи именно libucl (а, следовательно, поддержку всех форматов, что понимает ucl).


  1. wapmorgan
    01.06.2014 09:54

    До конца надеялся на исходники. Желаю удачи в реализации!


    1. amarao Автор
      01.06.2014 09:54

      Исходников есть примерно 40 строк. Показывать стыдно. Программист из меня фиговый, всё время срезать углы хочу.


      1. chemistmail
        01.06.2014 09:54

        У меня в моем проекте планируется набор системных утилит с выводом в json, попутно могу и для вас накидать.
        Только по времени быстро не обещаю, занят сейчас.
        язык Haskell


  1. Lsh
    01.06.2014 09:54

    Идея хорошая!

    Но >ls -la | ls2json | json-filter
    — это что-то не то, плохо сочетается с «hand-candy (мало печатать)». Получается что надо написать обычную команду, потом написать input — многословность получается. Взять и переделать базовые утилиты (чтобы они имели опцию вывода в json) наверное сложно, да и опция опять добавит многословность. Написать свои? Но тогда они будут некрасиво называться, типа jls, jps и т.п. Я подумал что хорошим решением будет некий набор оберток над стандартными утилитами, плюс набор алиасов (наверное все шеллы умеют алиасы).
    alias ls=json-ls
    При этом json-ls может как сам читать директории (т.е. написать свою реализацию), так и парсить вывод обычного ls'а.
    Когда json-ls запускается, он проверяет что на том конце пайпа. Если там утилита, которая понимает json (для этого в каждой json-утилите есть список «братьев и сестер»), то json-ls выдает json, если там что-то другое, то json-ls запускает обычный ls и передает ему все параметры. Думаю что оверхед будет небольшой.


  1. bubuq
    01.06.2014 09:54

    Требуется набор компилируемых утилит, верно я понимаю? Или решения в скриптовых средах катят? (perl, node, ruby, shell)?


    1. CRImier
      01.06.2014 09:54

      Собственно, уже что-то вырисовывается =) Скоро обсудим pull request и оно появится на своём законном месте.


  1. vovochka404
    01.06.2014 09:54

    Люди задаются этой идеей уже давно.
    Конкретно про json: theatticlight.net/posts/Why-cant-we-do-pipes-smarter/
    До этого где-то еще читал про предложения бинарных пайпов. Никак не могу найти.


  1. worldmind
    01.06.2014 09:54

    Вот же оно App::PipeFilters


  1. borv
    01.06.2014 09:54

    Много лет назад, когда мы еще дружили с перлом, я делал нечто похожее (даже с поддержкой CSV, JSON и XML). Собственно «расширение шелла» выглядело как кучка перл-прог, к которым со временем родился общий модуль для парсинга параметров из arg-ов и конфиг-файлов, сериализации объектов с сохранением типов и методов и т.д. Соответственно если у меня закисал мозг на каком-то однострочнике, я шел и писал прогу на перле. Да, сочленять перл-проги между собой через трубы было немного неэффективно (типа чтобы передать объект надо его заенкодить с одной стороны и задекодить с другой + динамически подгрузить его методы из общего модуля). И таки да, это занимало лишние 30 минут. Но, со временем, из зоопарка прог знание начало сегрегироваться в разумный набор утилит.

    Гонять хэши было довольно увлекательно, но потом из «личных нужд» это переросло в «очень перспективное решение», и пришлось выкинуть перлы и трубы, и взяться за java, ant (для кастомизации сценариев) и message bus. Увы.

    PS, кстати, отличная штука. И, наверное, .NET это плюс, а не минус, ибо зная API можно с ним поговорить, нарисовать свой cmdlet, даже если прога в явном виде это не позволяет. Что сильно более опенсоурсно и прогрессивно чем концепция «кучки черных ящичков» в никсах. Майки в этом смысле подняли планку.


    1. borv
      01.06.2014 09:54

      Я очень надеюсь, что поддержка PS на никсах это вопрос коммодитизации ОС и, следовательно, времени. Это было бы реально круто.


      1. amarao Автор
        01.06.2014 09:54

        Даже если MS решит всерьёз занятся продвижением PS на юниксах, оно очевидно будет плестись в хвосте у виндов (а у меня на виндоус всё работает, ничего не знаю), интересы юникс-платформы будут явно второстепенны перед платформой виндоус. Наверное, для пользователей виндоус это ок, но с точки зрения человека, у которого единственная винда на виртуалке — для криворукого drac'а на делловых серверах, это очевидная проблема.

        Если же посмотреть, во что превращается репозиторий ПО после установки mono, то становится страшно. Бесконечные перекомпиляции модулей при каждом апдейте превращают процесс apt-get update в подобие установки обновления .net' framework'а на винды — долго, безумно долго, отчаянно долго. И я не понимаю, почему надо добровольно в это нырять.

        Так что, спасибо, не надо.


    1. amarao Автор
      01.06.2014 09:54

      Признайтесь честно, overengineering — это кайф, а не зло, правда?

      Системы класса PoSh имеют две существенные проблемы:
      1) они считают окружающий их мир 'legacy' или 'внешними', 'untrusted' источниками данных, с которыми надо особо обращаться, и всячески от них уклоняться — всё должно быть сведено в уютный мир .net.
      2) Кривая вхождения такова, что человек либо всегда является профаном-любителем, либо его квалификация такова, что «а что он забыл в должности сисадмина?». То есть попытка объяснить в простых словах «как это устроено» (про любой командлет) потребует обширного курса по .net'у, более того, употребление и знание .net даёт явный плюс использующему. С точки зрения MS всё отлично — сложные скрипты на PoSh начинают напоминать обычную проприентарную магию (нашёл и скопипастил, работает, ура), а процесс изучения намертво подсаживает человека на платформу. Вместе с п.1 это делает мирок замкнутым и уютным.

      Я же хочу юникс-вей. Это когда каждая компонента очень проста по архитектуре, легко описуема и ни в один времени не вываливает на человека «дивный новый мир».


      1. borv
        01.06.2014 09:54

        Overengineering это метод борьбы с рутиной. Я вот сейчас рисую генератор мокапов по XML спеке вместо того, чтобы рисовать CRUD формочки в Visio. Меня трудно понять. Но, при этом, когда у меня получается, я делаю «80 часов работы до обеда» ;-)

        1) Posh-у вообще фиолетово кто на другом конце пайпа, лишь бы плевался объектами и вообще поддерживал метафору. Хотите — заверните вашу историческую действительность в cmdlet и радуйтесь.
        2) Да, Posh прицелен на DevOps. Это старая музыка под новую драм-машину, «пишущие админы». Майки очень на них ставят и, кстати, не зря. Большинство SaaS держится именно на них. Фанаты переименовывающие музыку в шеле их мало интересуют.

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


        1. amarao Автор
          01.06.2014 09:54

          overengineering, это когда вы потом окружающим предлагаете выучить все прилагающиеся технологии и начать пользоваться. Вне зависимости от того, есть ли время/желание у этих людей изучить эти технологии.

          Ещё хуже, когда вы перестаёте рисовать и просто начинаете сейлзам эти файлы присылать, мол, там всё просто.



  1. anonymous
    01.06.2014 09:54


    1. amarao Автор
      01.06.2014 09:54

      Круто. Мы пока что мучаемся с питонами, я итератор, Way, No — с input'ами. Го выглядит соблазнительно с точки зрения нативного кода.

      После прототипирования (пока не понятно как некоторые вещи делать) можно будет подумать о компилируемой реализации.


  1. vintage
    01.06.2014 09:54

    Я бы предложил вместо JSON использовать более другой формат.