Làm thế nào phức tạp một chương trình có thể được viết bằng Bash thuần túy? [đóng cửa]


17

Sau một số nghiên cứu rất nhanh, có vẻ như Bash là một ngôn ngữ hoàn chỉnh .

Tôi tự hỏi, tại sao Bash được sử dụng hầu như chỉ để viết các kịch bản tương đối đơn giản? Vì shell Bash đi kèm với Linux, bạn có thể chạy các kịch bản shell mà không cần bất kỳ trình thông dịch hoặc trình biên dịch bên ngoài nào, theo yêu cầu cho các ngôn ngữ máy tính phổ biến khác. Đây là một lợi thế rất lớn, có thể bù đắp cho sự tầm thường của ngôn ngữ trong một số trường hợp.

Vì vậy, có giới hạn về mức độ phức tạp của các chương trình như vậy không? Là Bash thuần túy được sử dụng để viết các chương trình phức tạp? Có thể viết, giả sử, một trình nén / giải nén tệp trong Bash thuần? Một trình biên dịch? Một trò chơi video đơn giản?

Có phải nó được sử dụng rất ít chỉ vì chỉ có các công cụ sửa lỗi rất hạn chế?


2
Các shkịch bản configuređược sử dụng như là một phần của quá trình xây dựng của rất nhiều un * x gói không phải là 'tương đối đơn giản.
dùng4556274

@ user4556274 Không phải vậy, nhưng nó thường không được viết bằng tay mà là từ một bộ m4macro rộng lớn .
Kusalananda

2
Có một trình biên dịch x86 trong Bash, vì vậy, thỉnh thoảng Bash được sử dụng để viết các chương trình phức tạp. Tại sao mọi người không làm điều đó thường xuyên hơn? Có thể bởi vì trình thông dịch cũng chậm chạp, nhảm nhí và nó dễ bị lỗi "thú vị" (xem fi Shellshock ). Ngoài ra, các tập lệnh Bash có xu hướng trở nên khó khăn hơn theo cấp số nhân. Nhìn vào trình biên dịch ở trên; bạn có thể cho biết từ nguồn nếu nó tuân theo cú pháp AT & T hoặc Intel không?
Satō Katsura

configurekịch bản cũng chậm, làm một loạt các công việc vô ích và đã trở thành chủ đề của một số lời tán dương thú vị. Tất nhiên, vỏ có thể được sử dụng cho các chương trình lớn, nhưng một lần nữa mọi người cũng đã tạo ra các máy tính từ Trò chơi Cuộc sống và Minecraft của Conway , và cũng có các ngôn ngữ lập trình như Brainf ** k và Hexagony . Rõ ràng một số người chỉ muốn xây dựng một cái gì đó từ các nguyên tử thực sự nhỏ và khó hiểu. Bạn thậm chí có thể bán các trò chơi với ý tưởng đó ...
ilkkachu

Vậy, câu hỏi này có trả lời được hay không? Họ giữ nó và nói rằng nó không thể trả lời được, nhưng tôi nhận được một vài câu trả lời tuyệt vời. Thật tuyệt khi được kết hợp, vì tôi là người mới của SE này, để hướng tôi đến loại câu hỏi nào và không mong muốn ở SE này.
Bregalad

Câu trả lời:


30

có vẻ như Bash là một ngôn ngữ hoàn chỉnh

Khái niệm về tính hoàn chỉnh của Turing hoàn toàn tách biệt với nhiều khái niệm hữu ích khác trong một ngôn ngữ để lập trình nói chung : tính khả dụng, tính biểu cảm, tính dễ hiểu, tốc độ, v.v.

Nếu Turing-đầy đủ là tất cả chúng ta được yêu cầu, chúng tôi sẽ không có bất kỳ ngôn ngữ lập trình nào cả , thậm chí không lắp ráp ngôn ngữ . Các lập trình viên máy tính tất cả sẽ chỉ viết mã máy , vì CPU của chúng tôi cũng đã hoàn tất.

Tại sao Bash được sử dụng hầu như chỉ để viết các kịch bản tương đối đơn giản?

Các tập lệnh shell lớn, phức tạp - chẳng hạn như configuretập lệnh đầu ra của GNU Autoconf - không điển hình vì nhiều lý do:

  1. Cho đến gần đây, bạn không thể tin tưởng vào việc có vỏ tương thích POSIX ở mọi nơi .

    Nhiều hệ thống, đặc biệt là các hệ thống cũ hơn, về mặt kỹ thuật có lớp vỏ tương thích POSIX ở đâu đó trên hệ thống, nhưng nó có thể không ở vị trí có thể dự đoán được như thế nào /bin/sh. Nếu bạn đang viết một kịch bản shell và nó phải chạy trên nhiều hệ thống khác nhau, vậy thì bạn viết dòng shebang như thế nào? Một lựa chọn là đi trước và sử dụng /bin/sh, nhưng chọn giới hạn bản thân với phương ngữ vỏ POSIX trước POSIX trong trường hợp nó được chạy trên một hệ thống như vậy.

    Các vỏ Bourne trước POSIX thậm chí không có số học tích hợp; bạn phải gọi ra exprhoặc bcđể hoàn thành nó

    Ngay cả với vỏ POSIX, bạn đang bỏ lỡ các mảng kết hợp và các tính năng khác mà chúng tôi dự kiến ​​sẽ tìm thấy trong các ngôn ngữ kịch bản Unix kể từ khi Perl lần đầu tiên trở nên phổ biến vào đầu những năm 1990 .

    Thực tế lịch sử đó có nghĩa là có một truyền thống kéo dài hàng thập kỷ bỏ qua nhiều tính năng mạnh mẽ trong phiên dịch kịch bản vỏ gia đình Bourne hiện đại hoàn toàn bởi vì bạn không thể tin vào việc có chúng ở mọi nơi.

    Thực tế điều này vẫn tiếp tục cho đến ngày nay, trên thực tế: Bash đã không nhận được các mảng kết hợp cho đến phiên bản 4 , nhưng bạn có thể ngạc nhiên khi có bao nhiêu hệ thống vẫn được sử dụng dựa trên Bash 3. Apple vẫn phát hành Bash 3 với macOS vào năm 2017 - rõ ràng là cho lý do cấp phép - và các máy chủ Unix / Linux thường chạy tất cả nhưng không được sản xuất trong một thời gian rất dài, do đó bạn có thể có một hệ thống cũ ổn định vẫn chạy Bash 3, chẳng hạn như hộp CentOS 5. Nếu bạn có các hệ thống như vậy trong môi trường của mình, bạn không thể sử dụng các mảng kết hợp trong các tập lệnh shell phải chạy trên chúng.

    Nếu câu trả lời của bạn cho vấn đề đó là bạn chỉ viết các kịch bản shell cho các hệ thống "hiện đại", thì bạn phải đối phó với thực tế là điểm tham chiếu chung cuối cùng cho hầu hết các shell Unix là tiêu chuẩn shell POSIX , phần lớn không thay đổi vì nó là được giới thiệu vào năm 1989. Có nhiều loại vỏ khác nhau dựa trên tiêu chuẩn đó, nhưng tất cả chúng đều được chuyển hướng đến các mức độ khác nhau so với tiêu chuẩn đó. Chịu mảng kết hợp một lần nữa, bash, zsh, và ksh93tất cả đều có tính năng đó, nhưng có nhiều sự không tương thích thực hiện. Do đó, lựa chọn của bạn là chỉ sử dụng Bash hoặc chỉ sử dụng Zsh hoặc chỉ sử dụng ksh93.

    Nếu câu trả lời của bạn cho vấn đề đó là "vậy thì cứ cài đặt Bash 4" hoặc ksh93, hoặc bất cứ điều gì, vậy thì tại sao không "chỉ" cài đặt Perl hoặc Python hoặc Ruby thay thế? Điều đó là không thể chấp nhận được trong nhiều trường hợp; mặc định vấn đề

  2. Không có ngôn ngữ kịch bản lệnh vỏ gia đình Bourne nào hỗ trợ các mô-đun .

    Gần nhất bạn có thể đến với một hệ thống mô-đun trong tập lệnh shell là .lệnh - hay còn gọi là sourcecác biến thể shell Bourne hiện đại hơn - không thành công ở nhiều cấp độ so với hệ thống mô-đun phù hợp, trong đó cơ bản nhất là không gian tên .

    Bất kể ngôn ngữ lập trình, sự hiểu biết của con người bắt đầu gắn cờ khi bất kỳ tệp nào trong một chương trình tổng thể lớn hơn vượt quá vài nghìn dòng. Lý do chúng tôi cấu trúc các chương trình lớn thành nhiều tệp là để chúng tôi có thể trừu tượng hóa nội dung của chúng thành một hoặc hai câu. Tệp A là trình phân tích cú pháp dòng lệnh, tệp B là bơm I / O mạng, tệp C là shim giữa thư viện Z và phần còn lại của chương trình, v.v. Khi phương pháp duy nhất của bạn để lắp ráp nhiều tệp vào một chương trình là bao gồm văn bản , bạn đặt giới hạn về mức độ lớn mà các chương trình của bạn có thể phát triển hợp lý.

    Để so sánh, nó sẽ giống như nếu ngôn ngữ lập trình C không có trình liên kết, chỉ có các #includecâu lệnh. Một phương ngữ C-lite như vậy sẽ không cần các từ khóa như externhoặc static. Những tính năng tồn tại để cho phép mô-đun.

  3. POSIX không định nghĩa một cách để phạm vi biến cho một hàm script shell duy nhất, ít hơn nhiều cho một tệp.

    Điều này có hiệu quả làm cho tất cả các biến toàn cầu , một lần nữa làm tổn thương tính mô đun và khả năng kết hợp.

    Có những giải pháp cho vấn đề này trong các vỏ hậu POSIX - chắc chắn là trong bash, ksh93zshít nhất - nhưng điều đó chỉ đưa bạn trở lại điểm 1 ở trên.

    Bạn có thể thấy tác động của điều này trong các hướng dẫn kiểu trong cách viết macro GNU Autoconf, ở đó họ khuyên bạn nên đặt tiền tố tên biến với tên của macro, dẫn đến các tên biến rất dài hoàn toàn để giảm khả năng va chạm đến gần số không.

    Thậm chí C là tốt hơn về điểm số này, bằng một dặm. Không chỉ hầu hết các chương trình C được viết chủ yếu bằng các biến cục bộ-hàm, C còn hỗ trợ phạm vi khối, cho phép nhiều khối trong một hàm duy nhất sử dụng lại tên biến mà không bị nhiễm chéo.

  4. Ngôn ngữ lập trình Shell không có thư viện chuẩn.

    Có thể lập luận rằng thư viện chuẩn của ngôn ngữ kịch bản lệnh shell là nội dung của PATH, nhưng điều đó chỉ nói rằng để đạt được bất kỳ hậu quả nào, một kịch bản shell phải gọi ra toàn bộ chương trình, có thể là một ngôn ngữ được viết bằng ngôn ngữ mạnh hơn bắt đầu với.

    Không có kho lưu trữ thư viện tiện ích shell nào được sử dụng rộng rãi như với CPAN của Perl . Nếu không có một thư viện lớn về mã tiện ích của bên thứ ba, một lập trình viên phải viết thêm mã bằng tay, vì vậy cô ta sẽ làm việc kém hiệu quả hơn.

    Ngay cả khi bỏ qua thực tế là hầu hết các tập lệnh shell dựa vào các chương trình bên ngoài thường được viết bằng C để thực hiện bất kỳ điều gì hữu ích, vẫn có tổng phí của tất cả các pipe()fork()exec()chuỗi cuộc gọi. Mô hình đó khá hiệu quả trên Unix, so với IPC và quá trình khởi chạy trên các HĐH khác, nhưng ở đây nó thay thế hiệu quả những gì bạn làm với một cuộc gọi chương trình con trong một ngôn ngữ kịch bản lệnh khác, vẫn hiệu quả hơn nhiều. Điều đó đặt một giới hạn nghiêm trọng về giới hạn trên của tốc độ thực thi tập lệnh shell.

  5. Các kịch bản Shell có rất ít khả năng tích hợp để tăng hiệu suất của chúng thông qua thực thi song song.

    Vỏ Bourne đã &, waitvà đường ống dẫn cho điều này, nhưng đó là phần lớn chỉ hữu ích cho việc soạn nhiều chương trình, chứ không phải để đạt được CPU hay I / O song song. Bạn không có khả năng chốt các lõi hoặc bão hòa một mảng RAID chỉ với kịch bản shell và nếu bạn làm như vậy, bạn có thể có thể đạt được hiệu suất cao hơn nhiều trong các ngôn ngữ khác.

    Đường ống nói riêng là những cách yếu để tăng hiệu suất thông qua thực hiện song song. Nó chỉ cho phép hai chương trình chạy song song và một trong hai chương trình có thể sẽ bị chặn trên I / O đến hoặc từ chương trình kia tại bất kỳ thời điểm nào.

    Có những cách ngày sau xung quanh điều này, chẳng hạn như xargs -PGNUparallel , nhưng điều này chỉ phá hủy đến điểm 4 ở trên.

    Với hiệu quả không có khả năng tích hợp để tận dụng tối đa các hệ thống đa bộ xử lý, các tập lệnh shell luôn chậm hơn một chương trình được viết tốt bằng ngôn ngữ có thể sử dụng tất cả các bộ xử lý trong hệ thống. Để lấy configurelại ví dụ về tập lệnh GNU Autoconf , nhân đôi số lượng lõi trong hệ thống sẽ làm rất ít để cải thiện tốc độ chạy của nó.

  6. Ngôn ngữ kịch bản lệnh Shell không có con trỏ hoặc tham chiếu .

    Điều này ngăn bạn thực hiện một loạt những điều dễ dàng thực hiện trong các ngôn ngữ lập trình khác.

    Đối với một điều, việc không thể tham chiếu gián tiếp đến một cấu trúc dữ liệu khác trong bộ nhớ của chương trình có nghĩa là bạn bị giới hạn trong các cấu trúc dữ liệu tích hợp . Shell của bạn có thể có các mảng kết hợp , nhưng chúng được thực hiện như thế nào? Có một số khả năng, mỗi khả năng có sự đánh đổi khác nhau: cây đỏ đen , cây AVLbảng băm là phổ biến nhất, nhưng có những cái khác. Nếu bạn cần một bộ trao đổi khác, bạn sẽ bị mắc kẹt, vì không có tài liệu tham khảo, bạn không có cách nào để cuộn bằng tay nhiều loại cấu trúc dữ liệu nâng cao. Bạn đang bị mắc kẹt với những gì bạn đã được đưa ra.

    Hoặc, đó có thể là trường hợp bạn cần một cấu trúc dữ liệu thậm chí không có một giải pháp thay thế phù hợp được tích hợp trong trình thông dịch kịch bản lệnh shell của bạn, chẳng hạn như biểu đồ chu kỳ có hướng , mà bạn có thể cần để mô hình biểu đồ phụ thuộc . Tôi đã lập trình trong nhiều thập kỷ và cách duy nhất tôi có thể nghĩ để làm điều đó trong tập lệnh shell là lạm dụng hệ thống tệp , sử dụng liên kết tượng trưng làm tài liệu tham khảo giả. Đó là loại giải pháp bạn nhận được khi bạn chỉ dựa vào Turing-perfect, nó không cho bạn biết gì về việc giải pháp đó có thanh lịch, nhanh chóng hay dễ hiểu hay không.

    Cấu trúc dữ liệu nâng cao chỉ đơn thuần là một sử dụng cho con trỏ và tham chiếu. Có hàng đống ứng dụng khác cho chúng , đơn giản là không thể thực hiện dễ dàng bằng ngôn ngữ kịch bản lệnh vỏ gia đình Bourne.

Tôi có thể tiếp tục và tiếp tục, nhưng tôi nghĩ rằng bạn đang nhận được điểm ở đây. Nói một cách đơn giản, có nhiều ngôn ngữ lập trình mạnh mẽ hơn cho các hệ thống loại Unix.

Đây là một lợi thế rất lớn, có thể bù đắp cho sự tầm thường của ngôn ngữ trong một số trường hợp.

Chắc chắn, và đó chính xác là lý do GNU Autoconf sử dụng một tập hợp con bị hạn chế có chủ đích của họ ngôn ngữ kịch bản shell của Bourne cho các configuređầu ra tập lệnh của nó : để các configuretập lệnh của nó sẽ chạy khá nhiều ở mọi nơi.

Bạn có thể sẽ không tìm thấy một nhóm tín đồ lớn hơn về tiện ích viết bằng phương ngữ vỏ Bourne có tính di động cao hơn các nhà phát triển GNU Autoconf, tuy nhiên sáng tạo của họ được viết chủ yếu bằng Perl, cộng với một số m4và chỉ một chút vỏ kịch bản; chỉ đầu ra của Autoconf là tập lệnh shell Bourne thuần túy. Nếu điều đó không đặt ra câu hỏi về khái niệm "Bourne ở mọi nơi" hữu ích như thế nào, thì tôi không biết điều gì sẽ xảy ra.

Vì vậy, có giới hạn về mức độ phức tạp của các chương trình như vậy không?

Về mặt kỹ thuật, không, như quan sát Turing-đầy đủ của bạn cho thấy.

Nhưng đó không phải là điều tương tự như khi nói rằng các tập lệnh shell lớn tùy ý dễ viết, dễ gỡ lỗi hoặc thực thi nhanh.

Có thể viết, giả sử, một trình nén / giải nén tệp trong bash thuần?

Bash "thuần khiết", không có bất kỳ lời kêu gọi nào đến những thứ trong PATH? Máy nén có thể sử dụng được echovà sử dụng các chuỗi thoát hex, nhưng sẽ khá khó khăn để làm. Bộ giải nén có thể không thể viết theo cách đó do không thể xử lý dữ liệu nhị phân trong shell . Cuối cùng, bạn sẽ gọi ra odvà như vậy để dịch dữ liệu nhị phân sang định dạng văn bản, cách xử lý dữ liệu gốc của shell.

Khi bạn bắt đầu nói về việc sử dụng shell scripting theo cách nó được dự định, như keo để điều khiển các chương trình khác trong PATH, cánh cửa mở ra, bởi vì bây giờ bạn chỉ giới hạn ở những gì có thể được thực hiện bằng các ngôn ngữ lập trình khác, nghĩa là bạn nói không có giới hạn nào cả. Một kịch bản sẽ thực tất cả sức mạnh của nó bằng cách gọi ra các chương trình khác trong PATHkhông chạy nhanh như các chương trình nguyên khối được viết bằng các ngôn ngữ mạnh hơn, nhưng nó không chạy.

Và đó là điểm chính. Nếu bạn cần một chương trình để chạy nhanh, hoặc nếu nó cần phải mạnh mẽ theo cách riêng của nó thay vì mượn sức mạnh từ người khác, bạn không nên viết nó vào vỏ.

Một trò chơi video đơn giản?

Đây là Tetris trong vỏ . Các trò chơi khác như vậy có sẵn, nếu bạn đi tìm.

chỉ có các công cụ sửa lỗi rất hạn chế

Tôi sẽ đặt công cụ gỡ lỗi xuống vị trí thứ 20 trong danh sách các tính năng cần thiết để hỗ trợ lập trình lớn. Toàn bộ các lập trình viên phụ thuộc rất nhiều vào việc printf()gỡ lỗi so với các trình sửa lỗi thích hợp, bất kể ngôn ngữ.

Trong shell, bạn có echoset -x, cùng nhau là đủ để gỡ lỗi rất nhiều vấn đề.


2
"Các kịch bản Shell có rất ít khả năng tích hợp để thực hiện song song." Theo tôi, shell có hỗ trợ xử lý song song tốt hơn hầu hết các ngôn ngữ khác. Với một ký tự duy nhất, &bạn có thể chạy các tiến trình song song. Bạn có thể waitcho các quá trình con hoàn thành. Bạn có thể thiết lập đường ống và mạng lưới đường ống phức tạp hơn bằng cách sử dụng đường ống có tên. Quan trọng nhất, thật đơn giản để xử lý song song đúng cách, với rất ít mã soạn sẵn và tránh các rủi ro và khó khăn của đa luồng bộ nhớ chia sẻ.
Sam Watkins

@SamWatkins: Tôi đã cập nhật điểm 5 ở trên để giải quyết câu trả lời của bạn. Mặc dù tôi cũng là một người hâm mộ truyền thông điệp giữa các quy trình riêng biệt như một cách để tránh nhiều vấn đề cố hữu trong song song bộ nhớ chia sẻ, điểm tôi đang nói ở đây là về việc tăng hiệu suất, không phải về khả năng kết hợp và như vậy, và đó là thường đòi hỏi song song bộ nhớ chia sẻ.
Warren Young

Các kịch bản Shell rất tốt cho tạo mẫu - nhưng cuối cùng một dự án nên chuyển sang ngôn ngữ lập trình phù hợp, sau đó lý tưởng là ngôn ngữ được biên dịch. Sau đó, trong trường hợp cực đoan lắp ráp, như bạn sẽ thấy với dự án FFmpeg. Cmake là một ví dụ điển hình về những gì sẽ xảy ra với Autotools - nó được viết bằng C và không yêu cầu Perl hoặc Texinfo hoặc M4. Thật đáng kinh ngạc khi Autotools vẫn phụ thuộc rất nhiều vào các kịch bản shell sau 30 năm wikipedia.org/wiki/GNU_Build_System#Criticism
Steven Penny

9

Chúng ta có thể đi bộ hoặc bơi ở bất cứ đâu, vậy tại sao chúng ta bận tâm với xe đạp, ô tô, xe lửa, thuyền, máy bay và các phương tiện khác? Chắc chắn, đi bộ hoặc bơi lội có thể mệt mỏi, nhưng có một lợi thế rất lớn trong việc không cần thêm bất kỳ thiết bị nào.

Đối với một điều, mặc dù bash là Turing-Complete, nhưng nó không tốt trong việc thao tác dữ liệu ngoài các số nguyên (không quá lớn), chuỗi, (một chiều) của chuỗi và ánh xạ hữu hạn từ chuỗi sang chuỗi. Bất kỳ loại dữ liệu nào khác cũng cần mã hóa khó chịu, khiến cho việc viết chương trình trở nên khó khăn và thường sẽ áp đặt hiệu suất không đủ tốt trong thực tế. Ví dụ, các phép toán dấu phẩy động trong bash rất khó và chậm.

Hơn nữa, bash có rất ít cách tương tác với môi trường của nó. Nó có thể chạy các quy trình, nó có thể thực hiện một số loại truy cập tệp đơn giản (thông qua chuyển hướng) và đó là về nó. Bash cũng có một máy khách kết nối phía máy khách. Bash có thể phát ra các byte null đủ dễ dàng ( printf \\0) nhưng không phân tích cú pháp null trong đầu vào của nó, điều này làm cho nó không phù hợp để đọc dữ liệu nhị phân. Bash không thể trực tiếp làm những việc khác: nó phải gọi các chương trình bên ngoài cho việc đó. Và đó là ok: shell được thiết kế cho mục đích chính là chạy các chương trình bên ngoài! Vỏ là ngôn ngữ keo để kết hợp các chương trình với nhau. Nhưng nếu bạn đang chạy một chương trình bên ngoài, điều đó có nghĩa là chương trình đó phải có sẵn - và sau đó bạn giảm lợi thế về tính di động:).

Bash không có bất kỳ loại tính năng nào giúp viết các chương trình mạnh mẽ dễ dàng hơn, ngoài việc set -e. Nó không có kiểu (hữu ích), không gian tên, mô-đun hoặc cấu trúc dữ liệu lồng nhau. Lỗi là khó khăn số một trong lập trình; trong khi việc dễ dàng viết các chương trình không có lỗi không phải lúc nào cũng là yếu tố quyết định trong việc chọn ngôn ngữ, bash xếp hạng kém về số đó. Bash cũng xếp hạng kém về hiệu suất khi làm những việc khác ngoài việc kết hợp các chương trình lại với nhau.

Trong một thời gian dài, bash không chạy trên Windows và thậm chí ngày nay nó không có trong bản cài đặt Windows mặc định và nó không chạy hoàn toàn tự nhiên (ngay cả trong WSL) theo nghĩa là nó không có giao diện với Các tính năng gốc của Windows. Bash không chạy trên iOS và không được cài đặt theo mặc định trên Android. Vì vậy, trừ khi bạn đang viết một ứng dụng chỉ dành cho Unix, bash hoàn toàn không khả dụng.

Yêu cầu một trình biên dịch không phải là một vấn đề cho tính di động. Trình biên dịch chạy trên máy của nhà phát triển. Yêu cầu một trình thông dịch hoặc thư viện của bên thứ ba có thể là một vấn đề, nhưng trong Linux, vấn đề được giải quyết thông qua các gói phân phối và trong Windows, Android và iOS, mọi người thường gói các thành phần của bên thứ ba trong gói ứng dụng của họ. Vì vậy, loại mối quan tâm về tính di động mà bạn có trong tâm trí không phải là mối quan tâm thiết thực đối với các ứng dụng hiện đại.

Câu trả lời của tôi áp dụng cho các vỏ khác ngoài bash. Một vài chi tiết khác nhau từ vỏ này sang vỏ khác nhưng ý tưởng chung là như nhau.


1
Tôi tin rằng huyền thoại về tính di động đã được nói đến khá thường xuyên, không chắc chắn tôi sẽ sử dụng mục cụ thể đó làm tiêu cực vì nó cũng áp dụng cho hầu hết các ngôn ngữ khác, bao gồm cả Java. Ngay cả PHP chạy trên máy chủ windows so với máy chủ * nix cũng có một số khác biệt nhỏ mà bạn luôn phải biết, nếu bạn đủ dại dột để chạy bất cứ thứ gì trên máy chủ windows, đó là. Rất nhiều thứ không chạy trên Android hoặc iOs nên không chắc đó có thể là một nhận xét hợp lệ.
Lizardx

7

Một số lý do không sử dụng tập lệnh shell cho các chương trình lớn, ngay trên đầu tôi:

  • Hầu hết các chức năng được thực hiện bằng cách loại bỏ các lệnh bên ngoài, chậm. Ngược lại, các ngôn ngữ lập trình như Perl có thể làm tương đương mkdirhoặc grepbên trong.
  • Không có cách nào dễ dàng để truy cập thư viện C hoặc thực hiện các cuộc gọi hệ thống trực tiếp, điều đó có nghĩa là trò chơi video sẽ khó tạo ra
  • Ngôn ngữ lập trình phù hợp có hỗ trợ tốt hơn cho các cấu trúc dữ liệu phức tạp. Mặc dù Bash không có mảng và mảng kết hợp, nhưng tôi không muốn nghĩ về một danh sách được liên kết hoặc một cái cây.
  • Shell được tạo để xử lý các lệnh được tạo nếu văn bản. Dữ liệu nhị phân (nghĩa là các biến chứa NUL byte (byte có giá trị 0)) khó có thể xử lý. Phụ thuộc một chút vào vỏ, zshcó một số hỗ trợ. Điều này cũng là do giao diện cho các chương trình bên ngoài chủ yếu dựa trên văn bản và \0được sử dụng làm dấu phân cách.
  • Cũng vì các lệnh bên ngoài, việc phân tách giữa mã và dữ liệu hơi khó khăn. Chứng kiến ​​tất cả những rắc rối xảy ra khi trích dẫn dữ liệu sang một shell khác (tức là khi chạy bash -c ...hoặc ssh -c ...)

Đây là tập hợp phủ định chính xác nhất đối với tôi, vì một người thực hiện nhiều tập lệnh bash lớn, đây sẽ gần như là những gì tôi sẽ liệt kê là tiêu cực. Tuy nhiên, một điều tôi đã tìm thấy là Bash thực sự không chậm hơn nhiều so với các ngôn ngữ được biên dịch khác khi so sánh chức năng tương tự. Tôi có một nghi ngờ lén lút là tôi đã cố gắng viết một số điều phức tạp hơn mà tôi gặp phải trong trăn, sự khác biệt về tốc độ sẽ không khiến công việc quái dị liên quan đến nó trở nên đáng giá. Tuy nhiên, một mình Bash tôi thấy quá hạn chế, nhưng Bash + gawk hoạt động tốt, gawk gần như có thật.
Lizardx
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.