Обсуждение: стандартные UNIX-утилиты, которые мало кто использовал и использует сейчас

    Неделю назад Дуглас Макилрой (Douglas McIlroy), разработчик конвейера UNIX и автор понятия «компонентно-ориентированное программирование», рассказал об интересных и необычных UNIX-программах, не нашедших широкого применения. Публикация запустила активное обсуждение на Hacker News. Мы собрали самое интересное и будем рады, если вы присоединитесь к дискуссии.


    Фото — Virginia Johnson — Unsplash

    Работа с текстом


    В UNIX-подобных операционных системах есть стандартный набор инструментов для форматирования текста. Утилита typo позволяла просматривать документ на наличие опечаток и гапаксов — слов, встречающихся в материале только один раз. Что интересно, для поиска опечаток программа не использует словари. Она опирается только на информацию в файле и проводит частотный анализ по триграммам (последовательность из трех символов). При этом все необходимые счетчики хранятся в массиве 26x26x26. По словам Дугласа Макилроя, такого объема памяти едва хватало для нескольких однобайтных счётчиков. Поэтому в целях экономии их писали в логарифмическом виде.

    Сегодня typo заменили более современные и точные программы проверки правописания на основе словарей. Однако про инструмент все еще помнят — несколько лет назад энтузиаст представил реализацию typo на Go. Репозиторий обновляется до сих пор.

    Еще один инструмент для работы с документами из 80-х — пакет Writer's Workbench от Лоринды Черри (Lorinda Cherry) и Нины Макдональд (Nina McDonald) из Bell Labs. В его состав входили инструменты для определения частей речи и стиля документа, поиска тавтологий и излишне сложных предложений. Утилиты разрабатывали в качестве подспорья для студентов, и одно время их использовали учащиеся Государственного университета Колорадо в США. Но к началу девяностых о Writer's Workbench позабыли, потому что его не включили в Version 7 Unix. Однако этот инструмент продолжил дорогу подражателям — например, Grammatik для IBM PC.

    В UNIX также имеются стандартные средства, упрощающие работу с формулами. Есть препроцессор языка для оформления математических выражений eqn. Он примечателен тем, что для отображения формулы разработчику достаточно описать её простыми словами и символами. Ключевые слова позволяют смещать математические знаки по вертикали и горизонтали, менять их размеры и другие параметры. Если передать утилите строку:

    sum from { k = 1 } to N { k sup 2 }

    На выходе будет сгенерирована следующая формула:

    $\sum_{k=1}^N k^2$


    В 1980–1990-х eqn помогал ИТ-специалистам писать мануалы к программному обеспечению. Но позже его заменила система LaTeX, которую использует даже Habr. Но eqn — это первый инструмент подобного класса, остающийся частью UNIX-подобных ОС.

    Работа с файлами


    В тематическом треде резиденты Hacker News отметили несколько редко используемых утилит для работы с файлами. Одной из них была comm для их сравнения. Это — упрощенный аналог diff, заточенный под работу в скриптах. Его написал сам Ричард Столлман (Richard Stallman) вместе с Дэвидом Маккензи (David MacKenzie).

    Вывод программы состоит из трех столбцов. В первую колонку попадают значения, уникальные для первого файла, во второй — уникальные для второго файла. Третий столбец включает общие значения. Для корректной работы comm сравниваемые документы должны быть лексически отсортированы. Поэтому один из резидентов площадки предложил работать с утилитой в следующем виде:

    comm <(sort fileA.txt) <(sort fileB.txt)

    Comm удобно использовать для проверки написания слов. Достаточно сравнивать их с эталонным документом-словарем. Учитывая тонкости, связанные с необходимостью сортировки файлов, есть мнение, что Столлман и Маккензи написали свою утилиту исключительно для этого юзкейса.


    Фото — Marnix Hogendoorn — Unsplash

    Также участник обсуждения на HN отметил возможности оператора paste, которые были для него неочевидны. Он позволяет чередовать потоки данных или разделить один поток на две колонки при выводе:

    $ paste <( echo -e 'foo\nbar' ) <( echo -e 'baz\nqux' )
    foo     baz
    bar     qux
    $ echo -e 'foo\nbar\nbaz\nqux' | paste - -
    foo     bar
    baz     qux
    

    Один из пользователей заметил, что часто для выполнения этих простых операций применяют не самые оптимальные решения: начиная с fmt, ex и заканчивая mlr с jot и rs.

    Какие стандартные возможности UNIX-подобных операционных систем стали открытием для вас?

    О чем мы пишем в нашем корпоративном блоге:

    Как развивалась система доменных имен: эра ARPANET
    История системы доменных имен: первые DNS-серверы
    История DNS: когда доменные имена стали платными
    История системы доменных имен: «войны» протоколов
    1cloud.ru
    IaaS, VPS, VDS, Частное и публичное облако, SSL

    Комментарии 9

      +5
      Есть утилита, которую многие используют и не знают, что это утилита
      /usr/bin/[
      :)
        0
        А многие думают, что используют, а на самом деле — нет, поскольку shell «не доводит до греха» (обращения к ФС) и справляется сама, будучи достаточно продвинутой для этого :)
          0

          Это bash так делает, а вот минималистичные вариации все же используют test, который [

            0
            да и bash в пайпе вызывает сам себя выполняя builtins. (обращаясь в ФС )
            кажется так.

            PS. Сейчас пишу проект в школе 21 про шелл и буду благодарен если кто поправит.
              0
              да и bash в пайпе вызывает сам себя выполняя builtins. (обращаясь в ФС )

              Что-то я не вижу запуска дочернего процесса в случае встроенного test.


              :) > strace -e trace=%process bash -c "[ 1 -eq 1 ]"
              execve("/bin/bash", ["bash", "-c", "[ 1 -eq 1 ]"], 0x7ffdeeebf7f0 /* 72 vars */) = 0
              arch_prctl(ARCH_SET_FS, 0x7f28dab7e740) = 0
              exit_group(0)                           = ?
              +++ exited with 0 +++
              
              :) > strace -e trace=%process bash -c "[[ 1 -eq 1 ]]"
              execve("/bin/bash", ["bash", "-c", "[[ 1 -eq 1 ]]"], 0x7fff57679a80 /* 72 vars */) = 0
              arch_prctl(ARCH_SET_FS, 0x7f89dfc60740) = 0
              exit_group(0)                           = ?
              +++ exited with 0 +++
              
              :) > strace -e trace=%process bash -c "/usr/bin/test 1 -eq 1"
              execve("/bin/bash", ["bash", "-c", "/usr/bin/test 1 -eq 1"], 0x7ffeeb49ed40 /* 72 vars */) = 0
              arch_prctl(ARCH_SET_FS, 0x7f9f5d72d740) = 0
              execve("/usr/bin/test", ["/usr/bin/test", "1", "-eq", "1"], 0x55caa9954ab0 /* 72 vars */) = 0
              arch_prctl(ARCH_SET_FS, 0x7fd2b445a540) = 0
              exit_group(0)                           = ?
              +++ exited with 0 +++

              :( > bash --version
              bash --version
              GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
              Copyright (C) 2016 Free Software Foundation, Inc.
              License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
              
              This is free software; you are free to change and redistribute it.
              There is NO WARRANTY, to the extent permitted by law.
              :) > lsb_release -a
              lsb_release -a
              No LSB modules are available.
              Distributor ID: Ubuntu
              Description:    Ubuntu 18.04.4 LTS
              Release:    18.04
              Codename:   bionic
              
                0
                а если в пайпе вызвать [ 1 -eq 1 ]?
        0
        Посмеялся, когда увидел, что за «энтузиаст» поддерживает форк typo на Go.
          0
          Видно, тоже повелся на хайп Go :)
          0
          А я недавно, пытаясь переделать для тещи plain text таблицу (нужно было изменить ширины рядов), на SO наткнулся на пример использования утилиты column. Удобная штука, и много разных параметров имеет…
          Пример:
          echo -e "a b c\n12 4312234 4341324\nllaoo asdf  fdaasd" | column -t          
          a      b        c
          12     4312234  4341324
          llaoo  asdf     fdaasd
          

          (но все равно пришлось делать при помощи awk!)

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.