Hơi bối rối về việc printf trong shell yash có phải là lệnh tích hợp hay không


14

Các yashvỏ có một printfbuilt-in, theo hướng dẫn của nó .

Tuy nhiên, đây là những gì tôi thấy trong một trình yashbao với cấu hình mặc định:

kk@eeyore ~ $ command -v printf
/usr/bin/printf
kk@eeyore ~ $ type printf
printf: a regular built-in at /usr/bin/printf

printfmột tích hợp trong vỏ này hay không? Kết quả tương tự đối với một số tiện ích được cho là tích hợp sẵn khác cũng có sẵn dưới dạng các lệnh bên ngoài.

Như một sự so sánh, trong pdksh( kshtrên OpenBSD, nơi printfkhông một built-in):

$ command -v printf
/usr/bin/printf
$ type printf
printf is /usr/bin/printf

Và trong bash(nơi printf một built-in):

$ command -v printf
printf
$ type printf
printf is a shell builtin

1
Đó là một tích hợp - thông thường , không phải là tích hợp đặc biệt . Nếu bạn đang nhầm lẫn về sự khác biệt giữa đặc biệtthường xuyên được xây dựng-in, hoặc hành vi bắt buộc theo tiêu chuẩn (xem tìm kiếm lệnh và thực hiện 1.eia) - trong đó đòi hỏi một nhị phân nên tồn tại trong PATHđể một thường xuyên built-in để được thực hiện - sau đó xin vui lòng đặt câu hỏi của bạn về điều đó.
mosvy

1
@mosvy Đây là một chi tiết về tiêu chuẩn mà tôi không biết. Nếu bạn muốn biến điều đó thành một câu trả lời, tôi sẽ rất vui. Tôi không nghĩ rằng tôi sẽ cần cập nhật câu hỏi để đây là một câu trả lời thích hợp, vì tôi không biết về chi tiết đặc biệt này. Hoặc tôi sẽ tự viết nó sau.
Kusalananda

Câu trả lời:


14

Các yashvỏ không có, và không sử dụng, một phiên bản tích hợp của printf(và các tiện ích khác). Nó chỉ xảy ra theo chuẩn POSIX theo phương pháp giáo dục theo cách nó tạo thành kết quả của các lệnh command -vtype.

Theo nhận xét của mosvy , tiêu chuẩn POSIX yêu cầu một lệnh tích hợp thông thường phải có sẵn như là một lệnh bên ngoài $PATHđể phiên bản tích hợp của lệnh được thực thi.

Đây là văn bản có liên quan từ tiêu chuẩn :

Lệnh Tìm kiếm và Thi hành

Nếu một lệnh đơn giản dẫn đến một tên lệnh và một danh sách các đối số tùy chọn, các hành động sau sẽ được thực hiện:

  1. Nếu tên lệnh không chứa bất kỳ ký tự <slash> nào, bước thành công đầu tiên trong chuỗi sau sẽ xảy ra:

    • a. Nếu tên lệnh khớp với tên của tiện ích tích hợp đặc biệt, tiện ích tích hợp đặc biệt đó sẽ được gọi.

      [...]

    • e. Mặt khác, lệnh sẽ được tìm kiếm để sử dụng biến môi trường PATH như được mô tả trong Biến môi trường XBD:
      • Tôi. Nếu tìm kiếm thành công:
        • a. Nếu hệ thống đã triển khai tiện ích dưới dạng hàm dựng sẵn thông thường hoặc dưới dạng hàm shell, thì nó sẽ được gọi vào thời điểm này trong tìm kiếm đường dẫn.
        • b. Mặt khác, shell thực thi tiện ích trong một môi trường tiện ích riêng biệt [...]
          [...]
      • ii. Nếu tìm kiếm không thành công, lệnh sẽ thất bại với trạng thái thoát là 127 và shell sẽ viết một thông báo lỗi.
  2. Nếu tên lệnh chứa ít nhất một <slash>, [...]

Điều này có nghĩa là đầu ra của command -v printfdấu hiệu cho thấy printflệnh đã được tìm thấy trong đường dẫn tìm kiếm, trong khi đầu ra của type printfbổ sung thêm rằng lệnh này là một lệnh dựng sẵn thông thường.

printflệnh được tìm thấy trong đường dẫn tìm kiếm và vì nó là một phần tử tích hợp thường xuyên, nên yashsẽ gọi phiên bản lệnh tích hợp của nó . Nếu printfđã không tìm thấy trong các con đường, và nếu yashvỏ được chạy trong POSIX-ly chế độ đúng, một lỗi có thể đã được tạo ra để thay thế.

yashTự hào là một vỏ rất tuân thủ POSIX, và điều này cũng đúng nếu chúng ta nhìn vào những gì POSIX nói vềcommand -v :

-v

Viết một chuỗi vào đầu ra tiêu chuẩn cho biết tên đường dẫn hoặc lệnh sẽ được shell sử dụng, trong môi trường thực thi shell hiện tại (xem Môi trường thực thi Shell ), để gọi command_name, nhưng không gọi command_name.

  • Các tiện ích, các tiện ích tích hợp thông thường , command_namesbao gồm một <slash>ký tự và bất kỳ hàm xác định thực hiện nào được tìm thấy bằng cách sử dụng PATHbiến (như được mô tả trong Tìm kiếm và Thực thi lệnh ), sẽ được viết dưới dạng tên đường dẫn tuyệt đối .

3
Có ai biết tại sao POSIX có yêu cầu này cho một lệnh bên ngoài tồn tại trước khi chạy lệnh tích hợp không?
studog

@studog Bạn có thể muốn hỏi rằng đó là một câu hỏi mới riêng biệt, có thể đề cập đến câu trả lời và / hoặc câu hỏi này.
Kusalananda


6

Vỏ Watanabe có ba loại tích hợp, được mô tả chi tiết trong hướng dẫn sử dụng. Tất cả các lệnh dựng sẵn cũng được liệt kê ở đó, nhưng người ta phải suy luận rằng một cái gì đó là một lệnh tích hợp "thông thường" do không có bất kỳ ghi chú nào nói rằng lệnh đó là "đặc biệt" hoặc "bán đặc biệt" được xây dựng trong. Xây dựng thường xuyên không được đánh dấu.

printflà một trong những "tích hợp" thường xuyên như vậy. Trong chế độ riêng, nó luôn được gọi, bất kể có lệnh bên ngoài nào được tìm thấy bởi tên đó hay không.

$ PATH = / usr / bin 
$ printf
printf: lệnh này yêu cầu một toán hạng
$ printf
printf: tích hợp thường xuyên tại / usr / bin / printf
$
$ PATH = / 
$ printf
printf: lệnh này yêu cầu một toán hạng
$ printf
printf: tích hợp thông thường (không tìm thấy trong $ PATH)
$

Nhưng khi posixly-correcttùy chọn shell được đặt, nó chỉ được tích hợp sẵn nếu lệnh bên ngoài có thể được tìm thấy trên PATH.

$ set --poseixly-true
$
$ PATH = / usr / bin 
$ printf
printf: lệnh này yêu cầu một toán hạng
$
$ PATH = / 
$ printf
yash: không có lệnh như vậy `printf '
$

Điều này thực sự phù hợp với những gì Thông số kỹ thuật Unix đơn nói và đã nói từ ít nhất là năm 1997.

Nó khác với vỏ Z, vỏ 93 Korn, vỏ Bourne Again và vỏ Debian Almquist, không ai trong số đó thực hiện hoặc ghi lại hành vi đó cho các phần mềm dựng sẵn thông thường. Ví dụ, trình bao Z, các tài liệu tích hợp thông thường luôn được tìm thấy, trước bước tìm kiếm PATH. Vỏ Shell Almquist cũng vậy. Và đó là những gì các shell này làm được, ngay cả khi được gọi như shvới các tùy chọn POSIX bật của chúng.

% / bin / exec -a sh zsh -c "PATH = /; gõ printf; printf"
printf là một vỏ dựng sẵn
zsh: printf: 1: không đủ đối số
% / bin / exec -a sh ksh93 -c "PATH = /; gõ printf; printf"
printf là một vỏ dựng sẵn
Cách sử dụng: printf [tùy chọn] định dạng [chuỗi ...]
% / bin / exec -a sh bash --poseix -c "PATH = / type printf; printf"
printf là một vỏ dựng sẵn
printf: cách sử dụng: printf [-v var] format [argument]
% / bin / exec -a sh dash -c "PATH = /; gõ printf; printf"
printf là một vỏ dựng sẵn
sh: 1: printf: cách sử dụng: định dạng printf [arg ...]
% 

Tuy nhiên, không chạy printfkhi nó không hoạt động PATHlà vỏ PD Korn, vỏ Bourne gia truyền và vỏ KBS MirBSD; bởi vì họ không có tích printfhợp ngay từ đầu. ☺

% / bin / exec -a sh `lệnh -v ksh` -c" PATH = /; gõ printf; printf "
không tìm thấy printf
sh: printf: không tìm thấy
% / bin / exec -a sh `lệnh -v oksh` -c" PATH = /; gõ printf; printf "
không tìm thấy printf
sh: printf: không tìm thấy
% / bin / exec -a sh `lệnh -v jsh` -c" PATH = /; gõ printf; printf "
không tìm thấy printf
sh: printf: không tìm thấy
% / bin / exec -a sh mksh -c "PATH = /; gõ printf; printf"
không tìm thấy printf
sh: printf: không tìm thấy
% ksh -c "gõ printf; printf"
printf là bí danh được theo dõi cho / usr / bin / printf
cách sử dụng: định dạng printf [đối số ...]
% oksh -c "gõ printf; printf"
printf là bí danh được theo dõi cho / usr / bin / printf
cách sử dụng: định dạng printf [đối số ...]
% jsh -c "gõ printf; printf"
printf được băm (/ usr / bin / printf)
cách sử dụng: định dạng printf [đối số ...]
% mksh -c "gõ printf; printf"
printf là bí danh được theo dõi cho / usr / bin / printf
cách sử dụng: định dạng printf [đối số ...]
$

Tốt Cảm ơn bạn đã xác nhận và thêm các bit cụ thể vào kiến ​​thức của tôi! Tôi thích cái vỏ này hơn rồi.
Kusalananda

-1

Các từ ngữ có thể được cải thiện.

Nếu shell ở chế độ posix set --posixly-correct::

Đối với các phần dựng sẵn thông thường không tồn tại trong PATH, phần này được in:

pushd: a regular built-in (not found in $PATH)

Đó là một mô tả rõ ràng: Nó là một nội dung dựng sẵn nhưng không có tệp thực thi nào có cùng tên trong PATH.

Tuy nhiên, đối với các phần dựng sẵn thông thường mà tên cũng tồn tại trong PATH, phần này được in:

echo: a regular built-in at /bin/echo

Điều này, dường như ngụ ý rằng việc thực thi tại / bin / echo sẽ được thực thi (điều này sẽ không được thực hiện). Tôi đề nghị thay đổi từ atthành also found in PATH at:

echo: a regular built-in also found in PATH at /bin/echo

sẽ làm cho một mô tả tốt hơn. Có lẽ kèm theo đó trong ngoặc đơn (như câu trả lời khác đã làm) có thể làm cho nó tốt hơn.


Trong chế độ POSIX, không có nội dung dựng sẵn thông thường sẽ hoạt động trừ khicũng được tìm thấy trong PATH.

Tuy nhiên, cả hai (POSIX) đặc biệt:

break colon continue dot eval exec exit export
readonly return set shift times trap unset

Và bán đặc biệt của yash (không đặc biệt cho POSIX):

alias bg cd command false fc fg getopts jobs
kill pwd read true umask unalias wait

nội dung vẫn hoạt động.

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.