Herhangi bir fonksiyonel benzeri unix kabuğu var mı?


18

Ben (gerçekten) fonksiyonel programlama için acemi (aslında sadece python kullanarak temas vardı) ama bir kabuk ortamında bazı liste yoğun görevler için iyi bir yaklaşım gibi görünüyor.

Böyle bir şey yapmak isterdim:

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

Bu tür özelliklere sahip herhangi bir Unix kabuğu var mı? Ya da python içinden kolay kabuk erişimine (komutlar, env / vars, readline, vb ...) izin veren bazı özellikler (fikir, python'un interaktif yorumlayıcısını bash'ın yerine kullanmaktır).

DÜZENLE:

Belki karşılaştırmalı bir örnek açıklığa kavuşabilirdi. Diyelim ki dir / dosyadan oluşan bir listem var :

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

Ve gerçekten basit bir görev yapmak istiyorum: tüm dosyaları dist / AND'e sisteme kopyalamak (bir oluşturma işleminin parçası):

Bash kullanma:

$ cp $ {dosya [*]} dist /
$ cd dist && rpm -Uvh $ ($ {files [*]} içindeki f için; $ f basename yapın; tamamlandı))

Bir "pitonik kabuk" yaklaşımı kullanarak (dikkat: bu hayali koddur):

FILES içindeki dosya için $ cp [os.path.join ('dist', os.path.basename (dosya))] 'dist'

Farkı görebiliyor musunuz? Demek istediğim bu. Henüz bu tür şeylerle bir kabuktan nasıl çıkamazsınız? Kabuktaki listeleri işlemek için gerçek bir acıdır, hatta çok yaygın bir görevdir: dosya listesi, PID listesi, her şeyin listesi.

Ve gerçekten, gerçekten, önemli bir nokta: herkesin bildiği sözdizimi / araçlar / özellikler kullanmak: sh ve python.

IPython iyi bir yönde dikiş yapıyor, ancak şişti: var name '$' ile başlıyorsa bunu yapar, '$$' ise bunu yapar. Sözdizimi "doğal" değil, birçok kural ve "geçici çözüm" ( [ ln.upper() for ln in !ls ] -> sözdizimi hatası)




4
Fonksiyonel programlamayı listelemekten biraz daha fazlası var. Eğer ana odak fonksiyonel kod yazıyorsanız, ben örnek olarak python almazdım.
pqnet

Yanıtlar:


10

Muhtemelen aradığınıza çok yakın bir Şema Kabuğu var. Ben kullanmadım.

GÜNCELLEME :

Kendim kurdum ve denedim. Scsh'ın gerçekten kullanışlı bir etkileşimli kabuktan çok etkileşimli bir şema yorumlayıcısı ve komut dosyası dili olduğu anlaşılıyor. Sadece yazamazsın

echo hello

sözdizimi

(run (echo hello))

ve bunu bulmak sadece birkaç dakika Googling sürdü. İlk örnek burada geçerli:

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

şu anlama gelir:

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

ancak bu size basit bir kabuk komutunun nasıl çalıştırılacağını söylemez .

Bu SSS girişi şöyle diyor:

4.6 scsh'ı etkileşimli kabuk olarak kullanabilir miyim?

Teknik olarak şunları yapabilirsiniz: "scsh" komutunu çalıştırın ve mevcut tüm scsh işlevleriyle bir Scheme 48 oturumu gireceksiniz. Ancak, bu etkileşimli işler için kesinlikle uygun değildir: komut satırı düzenleme, komut satırı geçmişi, dosya / işlev adı tamamlama, kısa sözdizimi vb. Yoktur.

Bu sorunları hafifletmek için Martin Gasbichler ve Eric Knauel, scsh'ın üstünde çalışan ve rahat bir etkileşimli ortam sağlayan Komutan S'yi yazdılar. Yeni özelliklerinden biri, birçok Unix komutunun çıktısını anlayabilmesi ve kullanıcının buna yararlı şekillerde göz atmasına ve manipüle etmesine izin vermesidir. Komutan S hakkında daha fazla bilgi, bunu açıklayan makalede bulunabilir: http://www.deinprogramm.de/scheme-2005/05-knauel/05-knauel.pdf Komutan S'nin nasıl temin edileceği ve yükleneceği ile ilgili talimatlar scsh Web sitesi: http://www.scsh.net/resources/commander-s.html

Belki de gerçek cevap budur.


7

Soruyu doğrudan cevaplama kategorisinde, Bash ve Zsh vb.Için fonksiyonel bir yedek olarak tasarlanan ES kabuğu vardır.

İkincisi, daha işlevsel standart kabuk yazmanıza yardımcı olma kategorisinde, pipemill tekniğini öğrenmeyi düşünün:

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

İlk while döngüsü işlevseldir keep(yalnızca döngüden çıkan null olmayan değerleri iletir) ve ikincisi ise each(yalnızca yan etkiler için harita).

Bu, kabuklarda fp'ye muazzam bir destek.

Bir kabukta daha fazla fp tarzında birçok şeyi ifade etmek mümkündür, olması gerektiği kadar kolay değildir. Görünüşe göre hepimiz bu kadar çok kullansak bile, daha iyi mermiler yapmak için fazla bir ilgi yok.


6

Standart Bourne tarzı kabukları ( sh, bash, kshvs.) zaten yapalım:

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

(Önce dove önce noktalı virgül gerektiğini unutmayın done.) Ayrıca, komutta yalnızca bir kez görünüyorsa bashve diğer kabuklarda şunu $repoyazabilirsiniz:

git clone $host/{repo1,repo2,repo3}

eminim, ve ben çok kullanıyorum. Peki lambda fonksiyonları gibi diğer şeyler ne olacak?

8
git clone $host/{repo1,repo2,repo3}fordöngü ile aynı şeyi yapmaz ; git cloneüç argümanla bir kez çağırır . Aynı şeyi yapan şey aslında nasıl git cloneçalıştığının bir ürünüdür ; diğer komutlar için geçerli olmayabilir. (Karşılaştırma echo foo bar baziçin echo foo; echo bar; echo baz, örneğin.)
Keith, Thompson'a

@caruccio olarak kullanmak FUN=eval 'git clone '"$host"'$0 için bir lambda tanımlamak için kullanabilirsinizfor repo in repo{1,2,3} ; do $FUN $repo ; done
pqnet

En büyük sorun, unix araçlarının genellikle yan etkilere sahip olması (dosyalara yazmak gibi), bu nedenle bunları işlevsel bir dilde yapmak istediğiniz gibi oluşturamazsınız.
weberc2

2

Şema Shell, scsh, gerçekten çok iyi.

Keith Thompson'ın belirttiği gibi, etkileşimli bir kabuk olarak yararlı değildir (Komutan S ilginç bir deney gibi gözükse de). Bunun yerine, tüm POSIX bağlarına sahip olmanın faydalı olduğu bağlamlar için mükemmel bir programlama dili - diğer unix uygulamalarını çağırmak istediğiniz durumları içerir. Birkaç düzineden fazla satırdan oluşan bir kabuk senaryosu, ne kadar düzgün yazsanız da, her zaman bir kesmek gibi hissedecektir sh; aksine, scsh kullanarak önemli programlar yazmanızı engelleyen hiçbir şey yoktur.

scsh çok kompakt değil (kısalık, sh-aile dillerinin hem gücü hem de zayıflığıdır), ancak güçlüdür.

Küçük ve büyük görevler için kullanışlı ve pratik olduğundan, scsh bu arada bir Şema ile kavramanın iyi bir yoludur (bu, hedefiniz olursa, bu günlerde doğrudan Racket'e de gidebilirsiniz).

İşlevsel dillerin avantajları sadece liste yoğun görevler için değildir (geçmişleri nedeniyle, bir veri yapısı olarak listeleri tercih etme eğilimindedirler) - doğru koolü içtikten sonra programları yazmanın gerçekten sağlam bir yoludur. yardımcı.

Sh tarzı mermilerin işlevsel olduğu anlamlı bir anlam yoktur ve Python sadece bir lambda fonksiyonuna sahip olduğu için marjinal anlamda işlevseldir.


2

Kabuklar mutlaka son derece etkileyici, yani daha az çizgi, jeton, vb.

Dilleri genellikle R, akçaağaç vb. Gibi kabuklar veya DSL'ler gibi özel bir amaç için tasarlayarak ifade ederiz. Ve C, C ++, Java vb.Gibi genel amaçlı dillerin çoğunda nispeten az ifade bulabilirsiniz.

Python, Perl, Ruby, vb. Kabuklara, ala ördek tipine benzer şekillerde daha anlamlı genel amaçlı dillerdir. Böylece DSL'ler onlara kaynak yapılır, matematik için ala Sage . Gerçek kabuk komutları için o kadar da iyi değil .

Şema, tüm parantezler nedeniyle bir DLS oluşturduğunuzda bile bu kadar etkileyici değildir.

Bununla birlikte, Haskell gibi muazzam bir ifadeye ve DSL'ler oluşturmak için büyük bir kapasiteye sahip fonksiyonel diller var. Haskell üzerinde bir kabuk oluşturmak için ilginç bir çaba vardır kaplumbağa ve Shelly .

Uygulamada, Haskell'in güçlü fakat kısıtlayıcı tip sisteminden dolayı çaba araçlarını içeren bir öğrenme eğrisi vardır, ancak önemli ölçüde ümit vaat etmektedirler.


1

İlk olarak, sahip olduğunuz "${files[@]}"her yerde kullanıyor olmalısınız ${files[*]}. Aksi takdirde boşluklar sizi mahvedecektir.

Kabuk zaten oldukça işlevsel; metin çıktısı açısından satır listeleri olduğunu düşünüyorsanız, grepöyle filter, xargsöyle map, vb. Borular çok işlevsel.

Kabuk kuşkusuz en uygun programlama ortamı değildir, ancak etkileşimli kullanım için Python'dan çok daha uygundur. API ve kullanıcı arayüzünün aynı olması çok güzel bir özelliğe sahip - her ikisini de aynı anda öğrenin.

Neden daha çok cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'tercih ettiğinizi anlamıyorum cp "${FILES[@]}" dist. İkincisi çok daha az yazıyor.


0

O "işlevsel" olmanın bilmem ama yapmayın da var rc olan scsh kağıt bahseder. Es için bir öncü.

Linux Mint'te (ve muhtemelen Debian, Ubuntu ...)

sudo apt-get install rc
man rc
rc
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.