LINUX.ORG.RU

Bash + GNUPlot vs. Perl + GNUPlot vs. Python

 , , ,


0

4

Всем доброго дня! Работаю в научной сфере. Недавно поменял область исследований, и теперь анализ результатов расчётов требует более знания куда более сложных вещей, чем мои базовые знания по bash и GNUPlot. Например, столкнулся с тем, что в bash извлечение информации из имён файлов не является простой процедурой (через BASH_REMATCH), а передача пользовательской функции аргумента, являющегося массивом, и его обработки внутри, суть, полный геморрой. Например, в папке содержится список текстовых файлов вида: <base>.N<N value>.<ext> где N принимает дискретные числовые значения от 5 до 1000, а extension определяет характеристику изучаемой системы. Внутри файлов >2 колонок с числовыми данными. В bash скрипте я извлекал значения N и ext и записывал в массивы. Далее планировалось создать файл, в котором содержались бы команды для GNUPlot. Массивы для N и ext содержат повторяющиеся элементы, что неприемлемо. На этом этапе выясняется, что создание простой, казалось бы, функции, которая будет проверять, содержится ли данный элемент в данном массиве - это просто жесть! Я проколебася часа 3, и всё равно в итоге fail. Недавно коллега сказал, что связка bash+GNUPlot для работы - это стандарт 20-летней давности, и сейчас повсеместно используется Perl или Python, с которыми я не знаком вообще. В свете этого вопрос: что бы вы порекомендовали для сравнительно быстрого изучения и повседневного решения задач, подобных описанной? Спасибо!


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

Virtuos86 ★★★★★
()

...создание простой, казалось бы, функции, которая будет проверять, содержится ли данный элемент в данном массиве - это просто жесть! Я проколебася часа 3, и всё равно в итоге fail.

in-array()
{
    local arr="${1}[@]" val="$2"
    for elem in "${!arr}"; do
        [[ $elem == $val ]] \
            && return 0
    done
    return 1
}

 

$ my_array=(a b c d f)
$ if in-array array 'a'; then echo Y; else echo N; fi
Y
$ if in-array array 'e'; then echo Y; else echo N; fi
N

что бы вы порекомендовали для сравнительно быстрого изучения

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

Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 2)

Тебе нужен ipython.
Через 3 дня ты вернёшься и скажешь «будь ты проклят, за то, что не рассказал мне это раньше»

zolden ★★★★★
()

используется Perl или Python, с которыми я не знаком вообще

Не проблема. Perl сразу выбрасываем на свалку истории, отдаем предпочтение Python и R.

outtaspace ★★★
()

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

anonymous
()

Тебе нужен или R, или NumPy+Pandas - и еще функции из SciPy.
R хорошо, но питон - это «клей» между нэйтивными либами (типа numpy), заточенными под конкретные задачи. Вдруг ты захочешь диалог выбора файлов добавить? А блокноты ipython - вообще не имеют аналогов.

Shadow ★★★★★
()
Ответ на: комментарий от Virtuos86

хотя бы из-за строгой типизации, исключений и подробных сообщений об ошибках.

как будто в perl этого нет

annulen ★★★★★
()

Гвидон, конечно же. Да и информации по нему больше.

Meyer ★★★★★
()
Ответ на: комментарий от Virtuos86

Virtuos86, спасибо за ответ.

Скажите, можно ли считать, что Python - это «всё в одном»? Т.е. один скриптовый файл и обрабатывает текстовый выхлоп расчётов и графики строит? А что на счёт прямого вызова команд оболочки: cp, mkdir, cd, find... - равно как и других скриптов? Нужны ли в Python для этого дополнительные костыли? Удобно ли работать с циклами, операторами условия?

Хотите сказать, что Perl не извещает об ошибках?

wswgG
() автор топика
Ответ на: комментарий от Evgueni

А как на счёт вызова команд оболочки для предварительной группировки файлов? В R это можно сделать без особых усилий?

wswgG
() автор топика
Ответ на: комментарий от wswgG

В R можно сделать всё. А усилия зависят от степени владения инструментом.

Я обычно для обработки пишу программу на C++ ибо объём данных которые приходится обрабатывать выходит за пределы возможностей R (таких областей очень мало), а клеем является Python. Ничто не мешает такие дурацкие вещи, как группировка файлов передать клею, вне зависимости от используемого инструмента.

Evgueni ★★★★★
()
Последнее исправление: Evgueni (всего исправлений: 1)
Ответ на: комментарий от Zmicier

Обидно тем не менее, но, в любом случае, спасибо за ответ.

Выходит, что:

1. ни в мануале bash, ни даже, например, на http://www.opennet.ru/docs/RUS/bash_scripting_guide/ нет чёткого инструктажа того, как, блин, нормально функции писать, в частности, как работать с аргументами-массивами. Например, вот такой конструкции ${1}[@] я не видел, зато пробовал {$1[@]}, равно как и ${!arr}. Всё это очень нелогично и непоследовательно. Вся обработка результатов будет постоянно происходить методом проб и ошибок: пробовать такие скобки/кавычки или иные - на это просто нет времени. Мне не за это деньги платят :) На всякий случай, порекомендуйте ваш ресурс для изучения bash? Просторы интернета не в счёт.

2. внутри пользовательской функции bash надо создать пару локальных переменных, в которые считываются аргументы! Это ли не извращение?

wswgG
() автор топика
Ответ на: комментарий от umren

удобство работы с shell commands в скрипте?

wswgG
() автор топика
Ответ на: комментарий от DELIRIUM

удобство работы с shell commands в коде, который всё обрабатывает?

wswgG
() автор топика
Ответ на: комментарий от Virtuos86

И что из перечисленного есть в Perl? Мы же про Perl 5, а не про 6 говорим, да?

Я не он, но отвечу в google забаненному.

Ошибки - во-о-от: https://www.tutorialspoint.com/perl/perl_error_handling.htm

Исключения:

eval {};
if ($@) {
...
}
или, для особых эстетов, во-о-т: http://search.cpan.org/~ash/TryCatch-1.003002/lib/TryCatch.pm

А строгая типизация для скриптов на фиг не нужна. Только под ногами путается.

anonymous
()
Ответ на: комментарий от wswgG

внутри пользовательской функции bash надо создать пару локальных переменных, в которые считываются аргументы! Это ли не извращение?

Нет, это не извращение, а хорошая привычка (good practice).

Настолько хорошая, что языков, что позволяют этого не делать — раз, два и обчелся. ГНУ Баш как-раз один из тех, что позволяет.

Zmicier ★★★★★
()
Ответ на: комментарий от wswgG

нет чёткого инструктажа того, как, блин, нормально функции писать
ни в мануале bash

Ну, прилагаемое руководство — это все-таки справочник по языку, а не учебник по программированию.

ни на http://www.opennet.ru/docs/RUS/bash_scripting_guide/

А то, что их нет в этом сборнике вредных советов, — тому я бы не удивлялся.

А за учебной литературой — это вам к материалам под редакцией Грега Вулиджа.

Zmicier ★★★★★
()
Ответ на: комментарий от wswgG

как, блин, нормально функции писать

Если кратко, то в процедурном стиле. В другие парадигмы ГНУ Баш не умеет.

в частности, как работать с аргументами-массивами

Никак. Аргументов-массивов быть не может. Передаем имя глобального массива ссылкой (reference).

зато пробовал {$1[@]}

Всё это очень нелогично и непоследовательно.

Напротив — вот как раз это весьма логично, здесь нет отдельного синтаксиса, все обрабатывается по общим правилам.

Логика такая: программа на Баше интерпретируется «послойно» — на прошлом этапе генерируется *программа* для следующего. Это как препроцессор в Си, только лучше, или как макросы в Лиспах, только хуже.

Так здесь ${!arr} раскрывается сначала в ${my_array[@]}, а затем в 'a' 'b' 'c' 'd' 'f'.

${1[@]} же — это все элементы массива с именем 1, а не my_array.

Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 2)
Ответ на: комментарий от wswgG

А чтобы вас окончательно запутать, могу сообщить, что с некоторых пор на Баше таки можно писать и почти так, как вы хотите, используя корновский тип переменных-ссылок:

in-array()
{
    local -n arr="$1"
    local val="$2"
    for elem in "${arr[@]}"; do
        [[ $elem == $val ]] \
            && return 0
    done
    return 1
}

Наверное, это даже более предпочтительно.

Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 1)

Кстати, на Перле можно сделать так. :)

[XXXXX]$ ls
a.N12.13  a.N12.14  a.N24.13  b.N11.33
[XXXXX]$ ls a.* | xargs -n 1 cat
perl
rulit
!
[XXXXX]$ ls | perl -e 'while (<>) {chomp; if (/^a\.N(\d+)\.(\d+)$/) {$nValues{$1}=$extensions{$2}=1; push @files,$_}} print "Files: " . join(", ", @files), "\nUnique N values: ". join (", ", keys %nValues), "\nUnique extensions values: " . join (", ", keys %extensions), "\n"; print "Files data (with cat, just for fun): "; foreach(@files){print "\n$_:\n"; $cmd = "cat $_"; print `$cmd`};'
Files: a.N12.13, a.N12.14, a.N24.13
Unique N values: 24, 12
Unique extensions values: 13, 14
Files data (with cat, just for fun):
a.N12.13:
perl

a.N12.14:
rulit

a.N24.13:
!
anonymous
()
Ответ на: комментарий от anonymous

В общем, ТС, давай свою задачку. Завтра утром проснусь и напишу как её решение на Перле выглядит. Пускай змееводы от зависти удавится! :)

anonymous
()

python, R, julia. Какой нафиг bash?

anonymous
()
Ответ на: комментарий от Virtuos86

И что из перечисленного есть в Perl?

Все. Правда для трейсов в случае ошибки придется подключить модуль

Мы же про Perl 5, а не про 6 говорим, да?

Естественно

annulen ★★★★★
()

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

* Если ты заметил, что скрипт представляет из себя не просто последовательность вызова программ, а реализует какой-то алгоритм или «бизнес-логику», перепиши его на полноценном языке программирования (хинт: портировать на perl будет проще всего, особенно если много вызовов внешних программ и используются $?, $! и т.п.)

* Изучи POSIX sh. Если его возможностей мало, это верный знак того, что надо переписать скрипт на полноценном языке

* Если все-таки приходится писать на (ba)sh, поставь shellcheck и проверяй почаще свой код

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)

* Для общего развития изучи awk, это офигительный инструмент для построчной обработки тестовых файлов, имеющих регулярную структуру (простые текстовые таблицы, файлы вроде /proc/self/smaps и т.п.). Реализация под названием «mawk» рвет по скорости любые скриптовые языки общего назначения. Если логика усложняется, скрипт легко превратить в перловый.

annulen ★★★★★
()

gnuplot не имеет никакого отношения к проектам GNU, поэтому не следует писать его как «GNUPlot», а только как [G|g]nuplot.

По сабжу: забудь про перл. Либо matlab|octave и gnuplot как рисовалка для последнего, либо python, точнее, python+numpy+scipy+sympy и matplotlib, либо, как тут сказали уже, R.

unanimous ★★★★★
()
Последнее исправление: unanimous (всего исправлений: 1)
Ответ на: комментарий от anonymous

Ошибки - во-о-от: https://www.tutorialspoint.com/perl/perl_error_handling.htm

Коды возврата — ок :)

Исключения:

eval {};
if ($@) {
...
}

Это говно, а не исключения. Какая в Перле иерархия исключений? Какое базовое исключение? Как в три строки налабать MyCoolException, чтобы его можно было бросать и ловить без...

или, для особых эстетов, во-о-т: http://search.cpan.org/~ash/TryCatch-1.003002/lib/TryCatch.pm

... всяких дырявых модулей с CPAN? Я же не заикаюсь про ООП, который можно наговнякать и прикрутить изолентой сбоку к ЯП. Кстати, исключения очень помогают получать информативные сообщения об ошибках, и не только в тех случаях, когла руками позаботились обработать подозрительные места.

Virtuos86 ★★★★★
()
Ответ на: комментарий от annulen

И что из перечисленного есть в Perl?


Все.

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

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Это говно, а не исключения

Хм... Я вообще не понимаю, зачем тебе в скрипте нужны исключения, но пример привёл! :) Если такого типа исключений не достаточно, фиговый, сверхсложный скрипт у тебя. А полноценную программу и на C++ написать, с GCC скомпелять можно, скриптовые языки для этого вообще не нужны. Но ТС ведь не этого надо.

anonymous
()
Ответ на: комментарий от Zmicier

А чтобы вас окончательно запутать, могу сообщить, что с некоторых пор на Баше

Вот именно, с недавних пор. А такие вещи всегда делалось через eval, ибо ${!var} не все shell-ы понимают, да и если ниже идёт обращение к элементам в нескольких местах, то удобнее иметь таки реальную копию массива и обращаться с массивом обычным синтаксисом:

#!/bin/bash

in-array()
{
    eval local -a arr='("${'$1'[@]}")'
    for elem in "${arr[@]}"; do
        [[ $elem == $2 ]] && return 0
    done
    return 1
}

my_array=(a b c d f)
if in-array my_array 'b'; then echo Y; else echo N; fi
if in-array my_array 'e'; then echo Y; else echo N; fi
vodz ★★★★★
()
Ответ на: комментарий от anonymous

Хорошо, я сходил по ссылке — исключения из наброса исключаем. Я был неправ, механизм исключений в Perl существует.

Virtuos86 ★★★★★
()

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

ZERG ★★★★★
()
Ответ на: комментарий от bookman900

Смотря что тебе нужно. У меня скрипты всё читают из файла, строят пачку графиков без проблем.

ZERG ★★★★★
()
Ответ на: комментарий от vodz

Я, конечно, извиняюсь, но вот именно из-за такого 3.14здеца я и хочу отказаться от bash: ", "", {!<arg>} - охренеть. Если и на Perl такая же хрень, которая кому-то может показаться красивой и элегантной, то переход равноценен замене шила на мыло, и мне в таком случае даром не сдался.

wswgG
() автор топика
Ответ на: комментарий от ZERG

Делаю (делал) точно также при помощи «here document». Вы так же или с помощью «нормальной» записи в файл?

wswgG
() автор топика
Ответ на: комментарий от bookman900

На bash делаю вот так (называется here document):

cat << MARK >> <file4gnuplot> <text> MARK gnuplot <file4gnuplot>

причём, если таких MARK в скрипте несколько, то для них метки MARK должны отличаться (3.14здец!!!), кроме того, в строках <text> не должно быть никаких табуляций или пробелов в начале строки, иначе будут трудности при натравливании gnuplot на файл.

wswgG
() автор топика
Ответ на: комментарий от wswgG

cat << MARK >> <file4gnuplot> <text> MARK gnuplot <file4gnuplot>

Вы мне парсер сломали. Я так понимаю, имеется в виду следующее:

cat << MARK >> file4gnuplot 
text
MARK

gnuplot file4gnuplot
Zmicier ★★★★★
()
Ответ на: комментарий от wswgG

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

ЛПП.

#!/bin/bash

cat << EOF
1
2
3
EOF

cat << EOF
a
b
c
EOF

 

$ ./test
1
2
3
a
b
c

Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 1)
Ответ на: комментарий от wswgG

кроме того, в строках <text> не должно быть никаких табуляций или пробелов в начале строки

Пробелов — да. Табуляторы — бога ради.

3.6.6 Here Documents
--------------------

This type of redirection instructs the shell to read input from the
current source until a line containing only WORD (with no trailing
blanks) is seen.  All of the lines read up to that point are then used
as the standard input (or file descriptor N if N is specified) for a
command.

   The format of here-documents is:
     [N]<<[-]WORD
             HERE-DOCUMENT
     DELIMITER

   No parameter and variable expansion, command substitution, arithmetic
expansion, or filename expansion is performed on WORD.  If any part of
WORD is quoted, the DELIMITER is the result of quote removal on WORD,
and the lines in the here-document are not expanded.  If WORD is
unquoted, all lines of the here-document are subjected to parameter
expansion, command substitution, and arithmetic expansion, the character
sequence '\newline' is ignored, and '\' must be used to quote the
characters '\', '$', and '`'.

   If the redirection operator is '<<-', then all leading tab characters
are stripped from input lines and the line containing DELIMITER.  This
allows here-documents within shell scripts to be indented in a natural
fashion.

— (info "(bash) Redirections")

Zmicier ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.