'chuyển đổi' dựa trên vỏ


7

Tôi muốn lấy nguồn (tức là không gọi ) một tập lệnh từ bất kỳ shell nào (bash / csh là mục tiêu chính, nhưng fish, zsh, ksh, và RC cũng sẽ rất thú vị).

Tôi muốn nếu tập lệnh có thể là một tệp duy nhất - tức là không phải là tệp cho mỗi phương ngữ shell.

Tôi có thể làm điều đó?

Tôi đang nghĩ về một cái gì đó tương tự như:

  if shell is bash then
    # bash code here
  else
    if shell is csh then
      # csh code here
    else
      if shell is xxxsh then
        # xxxsh code here
      fi
    endif
  fi

Vì vậy, tôi có thể làm:

csh% source my_script
bash$ . my_script

Vấn đề là - tất nhiên iflà không giống nhau trong mỗi phương ngữ, vì vậy tôi bằng cách nào đó cần sử dụng cú pháp hợp lệ cho mọi shell.

Biên tập

Phát hiện shell là bước đầu tiên để xác định shell trong script trong thời gian chạy đang làm rất tốt.

Một bước quan trọng không kém là làm thế nào mã cho các phần khác nhau cho shell nên được trích dẫn để không nhầm lẫn các shell khác. Hãy suy nghĩ: Làm thế nào bạn có thể trong phần bash có <<here_documentchứa tất cả các ký tự trong tất cả các kết hợp hợp pháp trong bash nhưng bất hợp pháp trong bất kỳ shell nào khác mà không gây nhầm lẫn cho các shell khác. Điều này không được bao phủ bởi bất kỳ câu trả lời / câu trả lời liên kết.


1
Điều này là có thể, nhưng nó thường đòi hỏi cách giải quyết rất cụ thể và cực kỳ thông minh. Tôi không nghĩ rằng thực sự có một cách chung chung và có thể mở rộng để làm điều đó.
Tom Hunt

4
Đây là một ví dụ về một số thông minh cực độ từ một trong số chúng ta: unix.stackexchange.com/a/71137/117549
Jeff Schaller


1
@ Hủy bỏ Tôi không nghĩ đây là một bản sao. OP ở đây muốn có thể thực thi một bộ hướng dẫn khác dựa trên lớp vỏ được sử dụng. Trong khi phát hiện vỏ thực sự là một phần của giải pháp, nó là không đủ. Khi bạn đã phát hiện ra nó, làm thế nào bạn có thể làm một thứ cho một vỏ và một vỏ khác cho một vỏ khác mà không tách các thứ thành các tệp khác nhau?
terdon

2
ngay cả khi điều này là có thể, bạn thực sự không muốn làm điều này. thay vì chịu đựng những điều kỳ lạ chỉ bằng một cái vỏ, bạn đang tự gây ra những điều kỳ quặc khủng khiếp với rất nhiều vỏ ốc trên mình.
cas

Câu trả lời:


2

Thay vì viết các đoạn mã cho mọi shell, bạn chỉ nên viết mã di động, có thể được hiểu bởi hầu hết các shell. Bạn nên xem ngôn ngữ lệnh POSIX Shell . Đây là một tiêu chuẩn làm thế nào một shell (tôn vinh POSIX) nên diễn giải mã.

Nhiều shell, như bash, có thể được cấu hình để hoạt động giống như shell POSIX. Mỗi vỏ có các tính năng chiến thắng và ký hiệu cụ thể của mình. Aviod chúng hoàn toàn trong các kịch bản di động.


3
OP đặc biệt đề cập đến csh, trong số nhiều thất bại khác của mình, chắc chắn là không tuân thủ POSIX nên điều này không có khả năng giúp họ nhiều.
terdon

1
Bất cứ ai viết kịch bản csh đều không nên và không nên tham khảo perl.com/doc/FMTEYEWTK/versus/csh.whynotshlomifish.org/open-source/anti/csh Quay trở lại thời kỳ đen tối của những năm 1980, csh đã thực hiện Shell tương tác khá tốt bởi vì nó có các tính năng gọn gàng như thu hồi và chỉnh sửa lịch sử. Khác, tốt hơn, shell từ lâu đã đạt được và vượt qua các tính năng đó mà không có nhược điểm của csh.
cas

2

Đối với giống như csh so với Bourne, bạn có thể làm:

start=:#||:<<"goto end="

echo "(t)csh code here"
if { bindkey >& /dev/null } then
  echo tcsh
endif

goto end=

echo Bourne-like code here
if [ -n "$BASH_VERSION" ]; then
  echo bash
fi

end=:

Giải thích:

  • start=:sẽ được coi là một khai báo nhãn cshvà gán biến sh, vì vậy hai hoạt động vô hại.
  • Trong start=:#đó, #được coi là một nhà lãnh đạo bình luận csh, nhưng không phải shlà một mã thông báo riêng biệt. Vì vậy, những gì sau đó được nhận xét cho cshnhưng không cho sh.
  • một phép gán biến shcó trạng thái thoát thành công (miễn là các phép gán không liên quan đến thay thế lệnh), do đó, lệnh bên phải của ||toán tử sẽ không được chạy.
  • :<<"goto end="...goto endLệnh đó không được chạy nhưng được phân tích cú pháp và bỏ qua (thực tế "goto end"được trích dẫn sẽ ngăn chặn các mở rộng khác nhau trong tài liệu ở đây). Tuy nhiên, một lưu ý: trong trình bao Bourne (và chỉ trong trình bao Bourne), một tệp tạm thời vẫn được tạo.
  • Vì vậy, toàn bộ phần cho đến khi goto end=được bỏ qua bởi vỏ giống như Bourne và chạy theo csh. goto end=nguyên nhân cshbỏ qua phần giữa đó và end=:(một phép gán biến vô hại trong các vỏ giống như Bourne).

Bạn càng hỗ trợ nhiều shell, nó càng phức tạp hơn. Đối với fishđặc biệt, nó khá phức tạp vì nó sẽ kiểm tra cú pháp của sự kiện kịch bản toàn bộ các phần nó không chạy.

Xem thêm:


-1

Tôi cho rằng lý do bạn muốn làm điều đó là vì tính di động. Các câu trả lời trên cung cấp cho bạn một đầu mối. Nếu bạn cho rằng, vỏ Bourne (sh) là mẫu số ít phổ biến nhất và có sẵn 'ở mọi nơi' (Linux, Solaris, Unix, AIX, v.v.) thì bạn có thể đặt #!/bin/shở đầu tập lệnh của mình và viết tất cả tập lệnh của bạn chỉ sử dụng các tính năng của sh. .

Một tinh chỉnh nhỏ là giả định rằng shnó luôn ở đó, nhưng bạn có thể cần thêm sức mạnh và sự tiện lợi của một số loại đạn tiên tiến hơn. để bạn có thể viết một phiên bản của tập lệnh cho từng trình bao bạn hỗ trợ, ví dụ script.bash, script.zsh, script.ksh, script.csh, v.v. mỗi tập bắt đầu bằng dòng shebang của riêng nó, và sau đó trong tập lệnh. sh tập tin bạn sẽ nói một cái gì đó như:

#!/bin/sh
if [[ -e /bin/ksh ]] ; then 
 ./script.ksh
 exit
elif [[ -e /bin/csh ]] ; then
 ./script.csh
 exit
fi

Vân vân.

Một gợi ý nữa là nghiên cứu mã nguồn của chuỗi công cụ tự động. Những thứ đó chạy khi bạn thực hiện ./mình; làm ; thực hiện cài đặt. Những người GNU đã làm rất nhiều điều thông minh để đảm bảo rằng các tập lệnh của họ chạy trong mọi môi trường.


OP đặc biệt đề cập đến việc họ muốn tránh có một tập lệnh riêng cho mỗi shell. Ngoài ra, giải pháp của bạn là kiểm tra sự tồn tại của các shell trên hệ thống, chứ không phải cho trình thông dịch hiện đang đọc tập lệnh, vì vậy điều đó cũng không giúp được gì. Cuối cùng, lưu ý rằng, những ngày này, shthường là một liên kết đến dash, nhưng ngay cả khi nó thực sự là một liên kết đến bash, gọi bashshnguyên nhân khiến nó chạy trong chế độ POSIX và hoạt động giống như truyền thống shhơn bash.
terdon
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.