1

Иногда нужно написать скрипт,  для  которого возможностей bash'а не хватает. С другой стороны, использование нормального ЯП тоже  не оправдано. К примеру,  bash  не умеет арифметику с вещественными числами(только  целые), ну  или bash  не умеет работать  с отдельными  символами(как с  байтами. Точнее умеет,  но работать  с символами неудобно).

Можно  использовать обычный  ЯП C, стандарта C99, и интерпретатор/компилятор tcc.

Вот простая  задача: посчитать  символы в тексте, и  вывести их  процентное  содержание. На bash, скрипт  будет  очень сложный  и  громоздкий, а вот  реализация  на сишке:

#!/usr/bin/tcc -run

#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main(int argc, char* argv[])
{
    const char* myname = basename(argv[0]);
    if(argc!=2)
    {
        fprintf(stderr, "Usage: %s FILENAME\n",
                myname);
        return 1;
    }
    int freq[256];
    int j;
    for(j=0; j<256; j++)    freq[j] = 0;

    FILE* fs = fopen(argv[1], "r");
    if(!fs)
    {
        fprintf(stderr, "%s:Can't open file '%s' (%s)\n", myname, argv[1], strerror(errno));
        return 1;
    }

    int c;
    while((c = fgetc(fs))!=EOF)
        freq[c]++;
    fclose(fs);


    double sum = 0.0;
    for(j=0; j<256; j++)    sum += freq[j];
    if(sum==0.0)
    {
        fprintf(stderr, "%s:File '%s' is empty\n", myname, argv[1]);
        return 1;
    }

    for(j=0; j<256; j++)
        if(freq[j]>0)
            printf("%d\t%c\t%d\t%f%%\n",
                    j,
                    j<=32 || j>=128? ' ': j,
                    freq[j],
                    (freq[j]/sum)*100);
    return 0;
}

пользоваться  этим можно  как с любым другим скриптом:  сохранить файл, дать право использования(выполнения), и запускать. К примеру я  сохранил в wcf.c

+ открыть спойлер

 Консоль:
$ ./wcf.c wcf.c
9         66    7.603687%
10         51    5.875576%
32         62    7.142857%
33    !    4    0.460829%
34    "    10    1.152074%
35    #    6    0.691244%
37    %    12    1.382488%
39    '    7    0.806452%
40    (    21    2.419355%
41    )    21    2.419355%
42    *    4    0.460829%
43    +    9    1.036866%
44    ,    15    1.728111%
45    -    1    0.115207%
46    .    7    0.806452%
47    /    4    0.460829%
48    0    13    1.497696%
49    1    8    0.921659%
50    2    7    0.806452%
51    3    1    0.115207%
53    5    4    0.460829%
54    6    4    0.460829%
56    8    1    0.115207%
58    :    4    0.460829%
59    ;    24    2.764977%
60    <    9    1.036866%
61    =    15    1.728111%
62    >    7    0.806452%
63    ?    1    0.115207%
65    A    1    0.115207%
67    C    1    0.115207%
69    E    4    0.460829%
70    F    4    0.460829%
73    I    2    0.230415%
76    L    2    0.230415%
77    M    1    0.115207%
78    N    1    0.115207%
79    O    1    0.115207%
85    U    1    0.115207%
91    [    12    1.382488%
92    \    7    0.806452%
93    ]    12    1.382488%
97    a    18    2.073733%
98    b    5    0.576037%
99    c    18    2.073733%
100    d    13    1.497696%
101    e    39    4.493088%
102    f    30    3.456221%
103    g    11    1.267281%
104    h    8    0.921659%
105    i    28    3.225806%
106    j    19    2.188940%
108    l    12    1.382488%
109    m    15    1.728111%
110    n    38    4.377880%
111    o    12    1.382488%
112    p    7    0.806452%
113    q    7    0.806452%
114    r    49    5.645161%
115    s    27    3.110599%
116    t    28    3.225806%
117    u    16    1.843318%
118    v    5    0.576037%
119    w    1    0.115207%
121    y    5    0.576037%
123    {    4    0.460829%
124    |    2    0.230415%
125    }    4    0.460829%

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

2

Да есть  Perl, Python...

В питоне можно использовать SQL запросы к БД...

3

спасибо, познавательно, но я тоже, когда не хватает баша, просто нерехожу на пайтон.

4

Ещё есть tk/tcl. Tcl - мощный shell-like interpreter.

Пётр.

Пётр.

5

Bif пишет:

Да есть  Perl, Python...

это всем  и  без вас известно. Я видел тонны быдлокода  и на том и  не другом.

Bif пишет:

В питоне можно использовать SQL запросы к БД...

ха! Удивили! Я на sed делал запросы к  СУБД. Надо будет, сделаю под brainfuсk.

Peter пишет:

Ещё есть tk/tcl. Tcl - мощный shell-like interpreter.

и что? Есть ещё Over9000  не менее "мощных" ЯП. А теперь расскажите,  зачем это ваше  не нужно вы юзаете?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

6

Спасибо, интересное решение.

dyasny пишет:

нерехожу на пайтон.

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

Истинный hotplug - это обычная электрическая розетка: воткнул - работает, и никаких драйверов.
Slackware64-current/Xfce/Lenovo G580

7

yars пишет:

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

довольно простой и удобный язык, особенно если невыеЖиваться и не вдаваться в пайтонизмы. Особенно хорош тем что сама структура синтаксиса заставляет писать читабельный код. Я сейчас похоже буду Go учить, хотя предпочел бы не распыляться

8

dyasny пишет:

когда не хватает баша, просто нерехожу на пайтон.

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

Есть ещё  плюс: возможность нативного использования  библиотек. Zlib, OpenSSL  например. А в питоне  оно на костылях, увы.

dyasny пишет:

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

быдлокодер и на питоне быдлокод писать  будет. Это не  лечится.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

9 (23.11.2014 07:33:10 отредактировано dyasny)

drBatty пишет:

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

когда его не достаточно можно и на С, но я RT не пишу, в основном автомацию всякую

drBatty пишет:

Есть ещё  плюс: возможность нативного использования  библиотек. Zlib, OpenSSL  например. А в питоне  оно на костылях, увы.

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

10

dyasny пишет:

когда его не достаточно можно и на С

ну  а  тут  _сразу_  на  C.

dyasny пишет:

но я RT не пишу

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

Смысл сабжевых скриптов  в том, что их не придётся  переписывать на C,  т.к.  они и так на C.

dyasny пишет:

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

ну  лично  мне  всё равно  нужно знать , как работать с библиотеками на C/C++. А изучать биндинги  X→Y  мне  лениво,  т.к.  ЯП я  знаю около  полусотни, а  всяких Y и того больше. И везде свои сложности.  В этих  ваших  питонах всяких  например  традиционная проблема с UTF-8,  а ещё проблема  версий(perl6, python3,  и  т.п.).

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

11

drBatty пишет:

ну  а  тут  _сразу_  на  C.

обычно его достаточно. не хватает не потому что функционала ЯП мало, а потому что надо работать не с объектами а с памятью напрямую например. Недавно как раз понадобился в срочном порядке прокси для бинарного потока, на пайтоне тормозило, сделали вставку которая читала из сокета в буфер, а потом писала в другой сокет на C. Вышло быстрее, да. Потом подумали еще раз и написали на пайтоне управлялку для iptables - оказалось еще быстрее

drBatty пишет:

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

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

drBatty пишет:

ну  лично  мне  всё равно  нужно знать , как работать с библиотеками на C/C++. А изучать биндинги  X→Y  мне  лениво,  т.к.  ЯП я  знаю около  полусотни, а  всяких Y и того больше. И везде свои сложности.  В этих  ваших  питонах всяких  например  традиционная проблема с UTF-8,  а ещё проблема  версий(perl6, python3,  и  т.п.).

везде свои проблемы, и все зависит от задач. C теряет смысл когда быстродействие не важно, зато надо писать большое количество сложного высокоуровневого функционала. Чтоб далеко не ходить - openstack отличный пример. Если бы его писали на С, его бы до сих пор не существовало.

12

dyasny пишет:

не хватает не потому что функционала ЯП мало,

дык  почти  все  ЯП тьюринг-полные,  даже на brainfuсk'е можно  писать что угодно.

dyasny пишет:

везде свои проблемы, и все зависит от задач. C теряет смысл когда быстродействие не важно, зато надо писать большое количество сложного высокоуровневого функционала. Чтоб далеко не ходить - openstack отличный пример. Если бы его писали на С, его бы до сих пор не существовало.

ну я вообще-то  про  короткие  скрипты говорил.

Что  до openstack, то  его  в  принципе и сейчас не  существует IRL. Это проект ИМХО.
Ну  и  потом, не  вижу  причин,  почему  проект нельзя  было реализовывать на C++  с STL? Оно  достаточно функциональное и  высокоуровневое для таких целей.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

13

drBatty пишет:
Peter пишет:

Ещё есть tk/tcl. Tcl - мощный shell-like interpreter.

и что? Есть ещё Over9000  не менее "мощных" ЯП. А теперь расскажите,  зачем это ваше  не нужно вы юзаете?

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

Пётр.

Пётр.

14

Peter пишет:

но у него удобный синтаксис, он похож на C.

ага.  Именно  что  "похож". А  на самом  деле, этот  ваш  тикель ближе  к  php, только  уродский.  Я на  нём  как-то писал что-то.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

15

dyasny пишет:

и не вдаваться в пайтонизмы

Можно пример?

«Я устал, я ухожу.»

16

Vitri пишет:

Можно пример?

l = [1, 2, 3, 4, 5]
print(sorted(l, key=lambda x: -x))

17

dyasny пишет:

l = [1, 2, 3, 4, 5] print(sorted(l, key=lambda x: -x))

это не  пайтонизм,  а  борщеедство  из LISP'а. Известно  с 60х годов прошлого века, но борщееды(уже третье поколение ЧСХ) до  сих пор на  это фапают. Если честно, я  тут не вижу ни чего  хорошего и  полезного.  IRL  это  всё не  нужно, и работает  лишь вот на  таких тестовых  примерах.

Алсо, в C++11 это тоже работает.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

18

drBatty пишет:

это не  пайтонизм,  а  борщеедство  из LISP'а. Известно  с 60х годов прошлого века, но борщееды(уже третье поколение ЧСХ) до  сих пор на  это фапают. Если честно, я  тут не вижу ни чего  хорошего и  полезного.  IRL  это  всё не  нужно, и работает  лишь вот на  таких тестовых  примерах.
Алсо, в C++11 это тоже работает.

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

19

JFF  добавил  сортировку  простыми вставками

#!/usr/bin/tcc -run

#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

void sort(const int* a[], int n)
{
    int j, k;
    const int* i;
    for(j=1; j<n-1; j++)
    {
        for(k=j+1, i=a[j+1]; k>0; k--)
        {
            if(*i>=*(a[k-1]))
                break;
            a[k] = a[k-1];
        }
        a[k] = i;
    }
}

int main(int argc, char* argv[])
{
    const char* myname = basename(argv[0]);
    if(argc!=2)
    {
        fprintf(stderr, "Usage: %s FILENAME\n",
                myname);
        return 1;
    }
    int freq[256];
    int j;
    for(j=0; j<256; j++)    freq[j] = 0;

    FILE* fs = fopen(argv[1], "r");
    if(!fs)
    {
        fprintf(stderr, "%s:Can't open file '%s' (%s)\n", myname, argv[1], strerror(errno));
        return 1;
    }

    int c;
    while((c = fgetc(fs))!=EOF)
        freq[c]++;
    fclose(fs);

    const int* a[256];
    for(j=0; j<256; j++)    a[j] = &freq[j];
    sort(a, 256);

    double sum = 0.0;
    for(j=0; j<256; j++)    sum += *(a[j]);
    if(sum==0.0)
    {
        fprintf(stderr, "%s:File '%s' is empty\n", myname, argv[1]);
        return 1;
    }

    for(j=0; j<256; j++)
        if(*(a[j])>0)
        {
            int k = a[j]-freq;
            printf("%d\t%c\t%d\t%f%%\n",
                    k,
                    k<=32 || k>=128? ' ': k,
                    *(a[j]),
                    (*(a[j])/sum)*100);
        }
    return 0;
}
Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)