Есть ли функциональная оболочка Unix?

18

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

Я хотел бы сделать что-то вроде этого:

$ [ git clone $host/$repo for repo in repo1 repo2 repo3 ]

Есть ли оболочка Unix с такими функциями? Или, может быть, какая-то функция, позволяющая легкий доступ к оболочке (команды, env / vars, readline и т. Д.) Изнутри python (идея состоит в том, чтобы использовать интерактивный интерпретатор python вместо замены bash).

РЕДАКТИРОВАТЬ:

Может быть, сравнительный пример уточнит. Допустим, у меня есть список, состоящий из dir / file :

$ FILES=( build/project.rpm build/project.src.rpm )

И я хочу сделать действительно простую задачу: скопировать все файлы в dist / и установить его в системе (это часть процесса сборки):

Используя bash:

$ cp $ {files [*]} dist /
$ cd dist && rpm -Uvh $ (для f в $ {files [*]}; сделать базовое имя $ f; сделано))

Используя подход «pythonic shell» (осторожно: это воображаемый код):

$ cp [os.path.join ('dist', os.path.basename (file)) для файла в файлах] 'dist'

Вы видите разницу? Вот о чем я говорю. Как еще нельзя выйти из оболочки с такими встроенными вещами? Работать со списками в оболочке очень сложно, даже если это такая распространенная задача: список файлов, список идентификаторов PID, список всего.

И действительно, очень важный момент: используя синтаксис / инструменты / функции, которые все уже знают: sh и python.

IPython выглядит хорошо, но он раздут: если имя переменной начинается с «$», он делает это, если «$$» это делает. Это синтаксис не "естественный", так много правил и "обходных путей" ( [ ln.upper() for ln in !ls ] -> синтаксическая ошибка)

caruccio
источник
Несколько связано: github.com/amoffat/pbs
Джош Ли
4
В функциональном программировании есть нечто большее, чем просто понимание списка. Если вы сосредоточены на написании функционального кода, я бы не стал использовать Python в качестве примера.
pqnet

Ответы:

10

Существует оболочка Scheme, которая, вероятно, очень близка к тому, что вы ищете. Я не использовал это сам.

ОБНОВИТЬ :

Я только что установил и попробовал это сам. Похоже, что scsh - больше интерактивный интерпретатор Scheme и язык сценариев, чем действительно полезная интерактивная оболочка. Вы не можете просто напечатать

echo hello

синтаксис выглядит так

(run (echo hello))

и потребовалось несколько минут, чтобы найти это. Первый пример здесь :

gunzip < paper.tex.gz | detex | spell | lpr -Ppulp &

что переводится как:

(& (| (gunzip) (detex) (spell) (lpr -Ppulp)) (< paper.tex.gz))

но это не говорит вам, как запустить простую команду оболочки.

Эта запись часто задаваемых вопросов говорит:

4.6 Могу ли я использовать scsh в качестве интерактивной оболочки?

Ну, технически вы можете: просто запустите команду "scsh", и вы войдете в сеанс Схемы 48 со всеми доступными функциями scsh. Однако это определенно не подходит для интерактивной работы: нет редактирования командной строки, истории командной строки, завершения имени файла / функции, краткого синтаксиса и т. Д.

Чтобы решить эти проблемы, Мартин Гасбихлер и Эрик Кнауэл написали Commander S, который работает поверх scsh и обеспечивает удобную интерактивную среду. Одна из его новых особенностей заключается в том, что он может понимать вывод многих команд Unix и позволяет пользователю просматривать и манипулировать им полезными способами. Более подробную информацию о Commander S можно найти в документе, описывающем его: http://www.deinprogramm.de/scheme-2005/05-knauel/05-knauel.pdf Инструкции о том, как получить и установить Commander S, можно найти в Веб-сайт scsh: http://www.scsh.net/resources/commander-s.html

Так что, возможно, это реальный ответ.

Кит Томпсон
источник
7

В категории прямого ответа на вопрос есть оболочка ES, которая предназначена для функциональной замены Bash, Zsh и т. Д.

Во-вторых, в категории, помогающей вам написать более функциональную стандартную оболочку, рассмотрите изучение техники pipemill:

who | while read username 
do
  cat <<EOF | grep $username
nic
mark
norman
keith
EOF
done | while read username
do
  echo "you have an answer on superuser.com" | mail -s "well done" $username
done

Первый цикл while - это функционал keep(передает только ненулевые значения, которые выходят из цикла), а второй - each(отображение только для побочных эффектов).

Это огромный импульс для fp в снарядах.

Можно выразить многие вещи в стиле fp в оболочке, это не так просто, как могло бы быть. Похоже, что делать лучшие снаряды не очень интересно, хотя мы все так часто их используем.

Nic Ferrier
источник
6

Стандартные оболочки Bourne-стиль ( sh, bash, kshи т.д.) уже позволяют сделать:

for repo in repo1 repo2 repo3 ; do git clone $host/$repo ; done

(Обратите внимание на необходимость использования точек с запятой перед doи done.) Кроме того, в bashи других оболочках, если $repoв команде появляется только один раз, вы можете написать:

git clone $host/{repo1,repo2,repo3}
jwodder
источник
конечно, и я часто этим пользуюсь. а как насчет других вещей, таких как лямбда-функции?
8
git clone $host/{repo1,repo2,repo3}не делает то же самое, что и forцикл; он вызывает git cloneодин раз с тремя аргументами. Тот факт, что, по сути, делает то же самое, является артефактом того, как git cloneработает; это не обязательно относится к другим командам. (Сравните echo foo bar bazс echo foo; echo bar; echo baz, например.)
Китом Томпсон
@caruccio, вы можете использовать FUN=eval 'git clone '"$host"'$0 для определения лямбда- for repo in repo{1,2,3} ; do $FUN $repo ; done
выражения
Самая большая проблема заключается в том, что инструменты Unix часто имеют побочные эффекты (например, запись в файлы), поэтому вы часто не можете составить их так, как вы хотели бы сделать на функциональном языке.
weberc2
2

Схема Shell, scsh, действительно хороша.

Как отмечает Кит Томпсон, он не используется в качестве интерактивной оболочки (хотя Commander S выглядит как интересный эксперимент). Это отличный язык программирования для контекстов, где полезно использовать все привязки POSIX, включая случаи, когда вы хотите вызывать другие приложения Unix. Сценарий оболочки из нескольких десятков строк всегда будет выглядеть как хак, независимо от того, насколько аккуратно вы пишете sh; напротив, ничто не мешает вам писать важные программы с использованием scsh.

scsh не очень компактен (краткость - это сила и слабость языков семейства sh), но он мощный.

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

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

Нет никакого осмысленного смысла в том, что оболочки в стиле sh являются функциональными, а Python функционален только в предельном смысле, что у него есть лямбда-функция.

Норман грей
источник
2

Оболочки обязательно чрезвычайно выразительны, а это значит, что вы добиваетесь большего с меньшим количеством линий, токенов и т. Д.

Мы обычно делаем языки выразительными, проектируя их для специальных целей, таких как оболочки или DSL, такие как R, maple и т. Д. И вы обнаружите относительно небольшую выразительность в большинстве языков общего назначения, таких как C, C ++, Java и т. Д.

Python, Perl, Ruby и т. Д. Являются языками общего назначения, которые более выразительны в способах, аналогичных оболочкам, а также типизированным утиным типом. Так что DSL привариваются к ним, аля Sage для математики. Не очень хорошо для реальных команд оболочки, хотя .

Схема не так уж и выразительна, даже когда вы строите DLS, из-за всех круглых скобок.

Однако существуют такие функциональные языки, как Haskell, с огромной выразительностью и большими возможностями для создания DSL. Интересными усилиями по созданию панциря на Хаскелле являются черепаха и ракушка .

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

Джефф Берджес
источник
1

Во-первых, вы должны использовать "${files[@]}"везде, где у вас есть ${files[*]}. В противном случае пробелы запутают вас.

Оболочка уже довольно функциональна; если вы думаете, что с точки зрения вывода текста это списки строк, то grepесть filter, xargsесть mapи т. д. Каналы очень функциональны.

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

Я не понимаю, почему вы считаете это cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'предпочтительным cp "${FILES[@]}" dist. Последний гораздо меньше печатает.

Марк Рид
источник
0

Не знаю, что это «функционально», но есть и rc , о котором упоминается в scsh paper . Это предшественник эс.

На Linux Mint (и, возможно, Debian, Ubuntu ...) вы можете попробовать это с

sudo apt-get install rc
man rc
rc
spelufo
источник