Czy jest jakaś funkcjonalna powłoka unixowa?

18

Jestem (naprawdę) nowicjuszem w programowaniu funkcjonalnym (w rzeczywistości miałem z nim kontakt tylko za pomocą Pythona), ale wydaje się być dobrym podejściem do niektórych zadań wymagających dużej ilości list w środowisku powłoki.

Chciałbym zrobić coś takiego:

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

Czy jest jakaś powłoka uniksowa z tego rodzaju funkcjami? A może jakaś funkcja umożliwiająca łatwy dostęp do powłoki (polecenia, env / vars, readline itp.) Z poziomu Pythona (pomysł polega na użyciu interaktywnego interpretera Pythona jako zamiennika bash).

EDYTOWAĆ:

Może wyjaśniłby to przykład porównawczy. Powiedzmy, że mam listę złożoną z katalogu / pliku :

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

Chcę wykonać naprawdę proste zadanie: skopiuj wszystkie pliki do dist / AND zainstaluj je w systemie (jest to część procesu kompilacji):

Za pomocą bash:

$ cp $ {pliki [*]} dist /
$ cd dist && rpm -Uvh $ (dla f w $ {pliki [*]}; do basename $ f; gotowe))

Korzystanie z podejścia „powłoki pythonowej” (uwaga: jest to urojony kod):

$ cp [os.path.join ('dist', os.path.basename (plik)) dla pliku w PLIKACH] 'dist'

Czy widzisz różnicę ? O tym właśnie mówię. Jak jeszcze nie wyjść z powłoki z tego typu wbudowanymi funkcjami? Naprawdę trudno jest obsługiwać listy w powłoce, nawet jeśli jest to tak częste zadanie: lista plików, lista PID, lista wszystkiego.

I naprawdę, bardzo ważny punkt: używając składni / narzędzi / funkcji, które wszyscy już znają: sh i python.

IPython wydaje się być w dobrym kierunku, ale jest rozdęty: jeśli nazwa var zaczyna się od „$”, robi to, jeśli „$$” to robi. Jego składnia nie jest „naturalna”, więc wiele reguł i „obejść” ( [ ln.upper() for ln in !ls ] -> błąd składni)

Caruccio
źródło
Nieco powiązane: github.com/amoffat/pbs
Josh Lee
4
Programowanie funkcjonalne to coś więcej niż tylko zrozumienie listy. Jeśli twoim głównym celem jest pisanie kodu funkcjonalnego, nie wziąłbym Pythona jako przykładu.
pqnet

Odpowiedzi:

10

Istnieje Skorupa Schematu, która prawdopodobnie jest bardzo zbliżona do tego, czego szukasz. Sam go nie użyłem.

AKTUALIZACJA :

Właśnie zainstalowałem i sam wypróbowałem. Wygląda na to, że scsh jest bardziej interaktywnym interpretatorem Scheme i językiem skryptowym niż naprawdę użyteczną interaktywną powłoką. Nie możesz po prostu pisać

echo hello

wydaje się, że składnia jest

(run (echo hello))

i znalezienie go zajęło Google kilka minut. Pierwszy przykład tutaj :

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

co przekłada się na:

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

ale to nie mówi, jak uruchomić proste polecenie powłoki.

Ten wpis FAQ mówi:

4.6 Czy mogę używać scsh jako interaktywnej powłoki?

Technicznie możesz: po prostu uruchomić polecenie „scsh” i wejdziesz w sesję Scheme 48 ze wszystkimi dostępnymi funkcjami scsh. Jednak zdecydowanie nie nadaje się to do pracy interaktywnej: nie ma edycji wiersza poleceń, historii wiersza poleceń, uzupełniania nazw plików / funkcji, składni zwięzłej itp.

Aby złagodzić te problemy, Martin Gasbichler i Eric Knauel napisali Commander S, który działa na scsh i zapewnia wygodne środowisko interaktywne. Jedną z jego nowatorskich cech jest to, że może zrozumieć wynik wielu poleceń Uniksa i umożliwia użytkownikowi przeglądanie i manipulowanie nim w użyteczny sposób. Więcej informacji o Commander S można znaleźć w dokumencie opisującym go: http://www.deinprogramm.de/scheme-2005/05-knauel/05-knauel.pdf Instrukcje dotyczące uzyskiwania i instalowania Commander S są dostępne na stronie Strona internetowa scsh: http://www.scsh.net/resources/commander-s.html

Więc może to jest prawdziwa odpowiedź.

Keith Thompson
źródło
7

W kategorii bezpośredniej odpowiedzi na pytanie znajduje się powłoka ES, która jest przeznaczona jako funkcjonalny zamiennik dla Bash i Zsh itp.

Po drugie, w kategorii pomocy w pisaniu bardziej funkcjonalnej standardowej powłoki, zastanów się nad techniką 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

Pierwsza pętla while jest funkcjonalna keep(przekazuje tylko niepuste wartości, które wychodzą z pętli), a druga to each(mapa tylko efektów ubocznych).

Jest to ogromny impuls do fp w pociskach.

Możliwe jest wyrażanie wielu rzeczy w stylu fp w powłoce, to po prostu nie jest tak łatwe, jak mogłoby być. Wydaje się, że nie ma większego zainteresowania tworzeniem lepszych pocisków, mimo że wszyscy tak często ich używamy.

ładniejszy przewoźnik
źródło
6

Standardowe muszle stylu Bourne'a ( sh, bash, ksh, itd.) Już pozwolić zrobić:

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

(Zwróć uwagę na potrzebę używania średników przed doi done.) Dodatkowo w bashi innych powłokach, jeśli $repopojawia się tylko raz w poleceniu, możesz napisać:

git clone $host/{repo1,repo2,repo3}
jwodder
źródło
jasne i bardzo go używam. ale co z innymi rzeczami, takimi jak funkcje lambda?
8
git clone $host/{repo1,repo2,repo3}nie robi tego samego, co forpętla; przywołuje git cloneraz z trzema argumentami. Fakt, że robi to w zasadzie to samo, jest artefaktem tego, jak git clonedziała; niekoniecznie dotyczy innych poleceń. (Porównaj echo foo bar bazcelu echo foo; echo bar; echo baz, na przykład.)
Keith Thompson
@ caruccio można użyć FUN=eval 'git clone '"$host"'$0 do zdefiniowania lambda do użycia jakofor repo in repo{1,2,3} ; do $FUN $repo ; done
pqnet
Największym problemem jest to, że narzędzia uniksowe często mają skutki uboczne (takie jak pisanie do plików), więc często nie można ich skomponować tak, jak chciałbyś to zrobić w funkcjonalnym języku.
weberc2
2

Schemat Shell, scsh, jest naprawdę dobry.

Jak zauważa Keith Thompson, nie jest on przydatny jako interaktywna powłoka (chociaż Commander S wygląda jak interesujący eksperyment). Zamiast tego jest to doskonały język programowania dla kontekstów, w których przydatne są wszystkie wiązania POSIX - w tym przypadki, w których chcesz wywoływać inne aplikacje uniksowe. Skrypt powłoki składający się z kilkudziesięciu wierszy zawsze będzie przypominał włamanie, bez względu na to, jak dobrze piszesz sh; w przeciwieństwie do tego nic nie powstrzymuje Cię przed pisaniem znaczących programów przy użyciu scsh.

scsh nie jest zbyt kompaktowy (zwięzłość jest zarówno siłą, jak i słabością języków rodziny sh), ale jest potężny.

Ponieważ jest przydatny i praktyczny w przypadku małych i dużych zadań, scsh jest zresztą dobrym sposobem na opanowanie programu (chociaż, jeśli to był twój cel, równie dobrze możesz teraz przejść bezpośrednio do Rakiety).

Zalety języków funkcjonalnych nie dotyczą tylko zadań wymagających dużej ilości list (choć z powodu ich historii preferują listy jako strukturę danych) - to naprawdę niezawodny sposób na pisanie programów, gdy wypijesz odpowiedni kool- pomoc.

Nie ma sensownego sensu, w którym powłoki w stylu sh są funkcjonalne, a Python działa tylko w marginalnym sensie, że ma funkcję lambda.

Norman Gray
źródło
2

Muszle są niezwykle wyraziste, co oznacza, że ​​osiągasz dużo przy mniejszej liczbie linii, tokenów itp.

Zazwyczaj wyrażamy języki, projektując je do specjalnego celu, takiego jak powłoki lub DSL, takie jak R, klon itp. W większości języków ogólnego przeznaczenia, takich jak C, C ++, Java itp., Można znaleźć stosunkowo mało wyrazistości.

Python, Perl, Ruby itp. To języki ogólnego przeznaczenia, które są bardziej ekspresyjne w sposób podobny do powłok, ala pisanie kaczek. Więc DSL przyspawane do nich, mędrca do matematyki. Jednak nie jest tak świetny do rzeczywistych poleceń powłoki .

Schemat nie jest tak wyrazisty, nawet po zbudowaniu DLS, ze względu na wszystkie nawiasy.

Istnieją jednak języki funkcjonalne, takie jak Haskell, z ogromną ekspresją i dużą zdolnością do tworzenia DSL. Ciekawym wysiłkiem zbudowania muszli na Haskell są żółwie i schronienia .

W praktyce istnieje krzywa uczenia się z narzędziami wysiłkowymi ze względu na potężny, ale restrykcyjny system Haskell, ale są one bardzo obiecujące.

Jeff Burdges
źródło
1

Po pierwsze, powinieneś używać "${files[@]}"wszędzie, gdzie masz ${files[*]}. W przeciwnym razie spacje zepsują cię.

Powłoka jest już dość funkcjonalna; jeśli myślisz, że w kategoriach tekstu wyjściowego są to listy linii, to grepznaczy filter, xargsjest mapitd. Rury są bardzo funkcjonalne.

Powłoka nie jest wprawdzie najbardziej przyjaznym środowiskiem programistycznym, ale znacznie lepiej nadaje się do użytku interaktywnego niż Python. I ma tę bardzo przyjemną cechę, że interfejs API i interfejs użytkownika są identyczne - ucz się obu naraz.

Nie rozumiem, dlaczego uważasz, że cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'lepiej cp "${FILES[@]}" dist. Ten ostatni jest o wiele mniej pisania.

Mark Reed
źródło
0

Nie wiem o tym, że jest „funkcjonalny”, ale jest też rc , o którym wspomina papier scsh . Jest to poprzednik es.

W Linux Mint (i prawdopodobnie Debian, Ubuntu ...) możesz tego spróbować

sudo apt-get install rc
man rc
rc
spelufo
źródło