Có bất kỳ vỏ unix chức năng?


18

Tôi (thực sự) mới làm quen với lập trình chức năng (thực tế chỉ tiếp xúc với nó bằng python) nhưng dường như là một cách tiếp cận tốt cho một số tác vụ chuyên sâu trong danh sách trong môi trường shell.

Tôi thích làm điều gì đó như thế này:

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

Có shell Unix nào với các loại tính năng này không? Hoặc có thể một số tính năng để cho phép truy cập shell dễ dàng (lệnh, env / vars, readline, v.v.) từ bên trong python (ý tưởng là sử dụng trình thông dịch tương tác của python để thay thế cho bash).

BIÊN TẬP:

Có lẽ một ví dụ so sánh sẽ làm rõ. Giả sử tôi có một danh sách gồm dir / file :

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

Và tôi muốn thực hiện một nhiệm vụ thực sự đơn giản: sao chép tất cả các tệp vào dist / AND cài đặt nó trong hệ thống (đó là một phần của quá trình xây dựng):

Sử dụng bash:

$ cp $ {tập tin [*]} dist /
$ cd dist && rpm -Uvh $ (với f trong $ {files [*]}; làm tên cơ sở $ f; xong))

Sử dụng phương pháp "vỏ pythonic" (lưu ý: đây là mã tưởng tượng):

$ cp [os.path.join ('dist', os.path.basename (tệp)) cho tệp trong PHIM] 'dist'

Bạn có thể thấy sự khác biệt ? Đó là những gì tôi đang nói về. Làm thế nào không thể thoát khỏi vỏ với các loại công cụ tích hợp này? Thật là một nỗi đau thực sự khi xử lý các danh sách trong shell, thậm chí nó là một nhiệm vụ rất phổ biến: danh sách các tệp, danh sách các PID, danh sách mọi thứ.

Và một điểm thực sự, thực sự, quan trọng: sử dụng cú pháp / công cụ / tính năng mà mọi người đều biết: sh và python.

IPython đường may là một hướng tốt, nhưng nó phình to: nếu tên var bắt đầu bằng '$', thì nó thực hiện điều này, nếu '$$' thì nó sẽ làm điều đó. Cú pháp của nó không phải là "tự nhiên", rất nhiều quy tắc và "cách giải quyết" ( [ ln.upper() for ln in !ls ] -> lỗi cú pháp)


Một số thứ liên quan: github.com/amoffat/pbs
Josh Lee


4
Có một chút nhiều hơn so với việc hiểu danh sách để lập trình chức năng. Nếu trọng tâm chính của bạn là viết mã chức năng, tôi sẽ không lấy python làm ví dụ.
pqnet

Câu trả lời:


10

Có một Scheme Shell có lẽ rất gần với những gì bạn đang tìm kiếm. Tôi đã không sử dụng nó cho mình.

CẬP NHẬT:

Tôi chỉ cần cài đặt và tự mình thử nó. Dường như scsh là một trình thông dịch và ngôn ngữ kịch bản tương tác hơn là một trình bao tương tác thực sự hữu ích. Bạn không thể chỉ gõ

echo hello

cú pháp dường như là

(run (echo hello))

và phải mất vài phút để Google tìm thấy điều đó. Ví dụ đầu tiên ở đây là:

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

dịch ra:

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

nhưng điều đó không cho bạn biết làm thế nào để chạy một lệnh shell đơn giản .

Mục FAQ này cho biết:

4.6 Tôi có thể sử dụng scsh làm vỏ tương tác không?

Vâng, về mặt kỹ thuật bạn có thể: chỉ cần chạy lệnh "scsh" và bạn sẽ nhập phiên Scheme 48 với tất cả các chức năng scsh có sẵn. Tuy nhiên, điều này chắc chắn không phù hợp với công việc tương tác: không có chỉnh sửa dòng lệnh, không có lịch sử dòng lệnh, không hoàn thành tên tệp / chức năng, không có cú pháp ngắn gọn, v.v.

Để giảm bớt những vấn đề này, Martin Gasbichler và Eric Knauel đã viết Commander S, chạy trên scsh và cung cấp một môi trường tương tác thoải mái. Một trong những tính năng mới của nó là nó có thể hiểu đầu ra của nhiều lệnh Unix và cho phép người dùng duyệt và thao tác nó theo những cách hữu ích. Thông tin thêm về Commander S có thể được tìm thấy trong bài báo mô tả nó: http://www.deinprogramm.de/scheme-2005/05-knauel/05-knauel.pdf Hướng dẫn về cách lấy và cài đặt Commander S có sẵn từ Trang web scsh: http://www.scsh.net/resource/commander-s.html

Vì vậy, có lẽ đó là câu trả lời thực sự.


7

Trong danh mục trả lời trực tiếp câu hỏi, có lớp vỏ ES được dùng để thay thế chức năng cho Bash và Zsh, v.v.

Thứ hai, trong danh mục giúp bạn viết shell tiêu chuẩn chức năng hơn, hãy xem xét việc học kỹ thuật 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

Vòng lặp while đầu tiên là một hàm keep(chỉ truyền các giá trị không null đi ra khỏi vòng lặp) và vòng thứ hai là một each(chỉ ánh xạ cho các hiệu ứng phụ).

Đây là một sự thúc đẩy to lớn cho fp trong shell.

Có thể diễn đạt nhiều thứ theo kiểu fp hơn trong một vỏ, nó không dễ như có thể. Có vẻ như không có nhiều hứng thú trong việc tạo ra những chiếc vỏ tốt hơn, mặc dù tất cả chúng ta đều sử dụng chúng rất nhiều.


6

Vỏ Bourne kiểu tiêu chuẩn ( sh, bash, ksh, vv) đã cho phép bạn thực hiện:

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

(Lưu ý sự cần thiết của dấu chấm phẩy trước dodone.) Ngoài ra, trong bashvà các shell khác, nếu $repochỉ xuất hiện một lần trong lệnh, bạn có thể viết:

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

chắc chắn, và tôi sử dụng nó rất nhiều. Nhưng những thứ khác, như chức năng lambda thì sao?

8
git clone $host/{repo1,repo2,repo3}không làm điều tương tự như forvòng lặp; nó gọi git clonemột lần với ba đối số. Thực tế về cơ bản điều tương tự là một sự giả tạo về cách thức git clonehoạt động; nó không nhất thiết phải áp dụng cho các lệnh khác. ( Ví dụ, so sánh echo foo bar bazvới echo foo; echo bar; echo baz.)
Keith Thompson

@caruccio bạn có thể sử dụng FUN=eval 'git clone '"$host"'$0 để xác định lambda để sử dụng nhưfor repo in repo{1,2,3} ; do $FUN $repo ; done
pqnet

Vấn đề lớn nhất là các công cụ unix thường có tác dụng phụ (như ghi vào tệp), vì vậy bạn thường không thể soạn chúng như bạn muốn làm bằng ngôn ngữ chức năng.
weberc2

2

Scheme Shell, scsh, thực sự tốt.

Như Keith Thompson lưu ý, nó không hữu ích như một vỏ tương tác (mặc dù Commander S trông giống như một thử nghiệm thú vị). Thay vào đó, nó là một ngôn ngữ lập trình tuyệt vời cho các bối cảnh trong đó có tất cả các ràng buộc POSIX là hữu ích - bao gồm các trường hợp bạn muốn gọi các ứng dụng unix khác. Một kịch bản shell gồm hơn vài chục dòng sẽ luôn có cảm giác như một bản hack, bất kể bạn viết gọn gàng đến mức nào sh; ngược lại, không có gì ngăn cản bạn viết các chương trình quan trọng bằng scsh.

scsh không nhỏ gọn lắm (sự ngắn gọn vừa là điểm mạnh vừa là điểm yếu của ngôn ngữ gia đình sh), nhưng nó rất mạnh mẽ.

Bởi vì nó hữu ích và thiết thực cho các nhiệm vụ lớn và nhỏ, scsh tình cờ là một cách tốt để nắm bắt được Lược đồ (mặc dù, nếu điều đó xảy ra là mục tiêu của bạn, bạn cũng có thể đi thẳng đến Vợt trong những ngày này).

Ưu điểm của ngôn ngữ chức năng không chỉ dành cho các tác vụ chuyên sâu trong danh sách (mặc dù vì lịch sử của chúng, chúng có xu hướng ưu tiên các danh sách dưới dạng cấu trúc dữ liệu) - đó là một cách thực sự mạnh mẽ để viết chương trình, một khi bạn uống đúng kool- viện trợ.

Không có ý nghĩa có ý nghĩa trong đó các vỏ kiểu sh là chức năng và Python chỉ hoạt động theo nghĩa cận biên rằng nó có chức năng lambda.


2

Shell nhất thiết phải cực kỳ biểu cảm, có nghĩa là bạn đạt được rất nhiều với ít dòng, mã thông báo, v.v.

Chúng tôi thường tạo ra các ngôn ngữ biểu cảm bằng cách thiết kế chúng cho một mục đích đặc biệt, như shell hoặc DSL như R, maple, v.v. Và bạn thấy tương đối ít biểu cảm trong hầu hết các ngôn ngữ có mục đích chung như C, C ++, Java, v.v.

Python, Perl, Ruby, v.v. là những ngôn ngữ có mục đích chung có tính biểu cảm cao hơn theo cách tương tự như shell, gõ vịt ala. Vì vậy, DSL được hàn vào chúng, ala Sage cho toán học. Không phải là quá tuyệt vời cho các lệnh shell thực tế mặc dù .

Lược đồ không phải là biểu cảm, ngay cả khi bạn xây dựng DLS, do tất cả các dấu ngoặc đơn.

Tuy nhiên, có những ngôn ngữ chức năng như Haskell với tính biểu cảm to lớn và khả năng tuyệt vời để xây dựng DSL. Nỗ lực thú vị để xây dựng một chiếc vỏ trên Haskell là rùashelly .

Trong thực tế, có một đường cong học tập với các công cụ nỗ lực do hệ thống loại mạnh mẽ nhưng hạn chế của Haskell, nhưng chúng cho thấy nhiều hứa hẹn.


1

Đầu tiên, bạn nên sử dụng "${files[@]}"ở mọi nơi bạn có ${files[*]}. Nếu không không gian sẽ làm phiền bạn.

Shell đã khá chức năng rồi; nếu bạn nghĩ về sản lượng văn bản phúc danh sách các dòng, sau đó grepfilter, xargsmapvv Ống rất chức năng.

Shell được thừa nhận không phải là môi trường lập trình thân thiện nhất, nhưng nó phù hợp hơn với việc sử dụng tương tác so với Python. Và nó có một tính năng rất hay là API và UI giống hệt nhau - học cả hai cùng một lúc.

Tôi không hiểu tại sao bạn thấy cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'thích hơn cp "${FILES[@]}" dist. Cái sau ít gõ hơn nhiều.


0

Không biết nó là "chức năng", nhưng cũng có RC , mà tờ scsh đề cập. Đó là một tiền thân của es.

Trên Linux Mint (và có thể là Debian, Ubuntu ...) bạn có thể dùng thử với

sudo apt-get install rc
man rc
rc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.