Có sự khác biệt giữa đọc, đầu -1 và sed 1q không?


7

Các lệnh sau có vẻ tương đương nhau:

read varname
varname=$(head -1)
varname=$(sed 1q)

Một điểm khác biệt là readvỏ được tích hợp sẵn trong khi headsedkhông.

Bên cạnh đó, có sự khác biệt nào trong hành vi giữa ba người không?

Động lực của tôi là để hiểu rõ hơn các sắc thái của vỏ và các tiện ích chính như thế nào head,sed. Ví dụ: nếu sử dụng headlà một sự thay thế dễ dàng cho readthì tại sao lại readtồn tại dưới dạng dựng sẵn?

Câu trả lời:


6

Không hiệu quả cũng không phải xây dựng là sự khác biệt lớn nhất. Tất cả chúng sẽ trả lại đầu ra khác nhau cho đầu vào nhất định.

  • head -n1 sẽ cung cấp một dòng mới chỉ khi đầu vào có một.

  • sed 1q sẽ luôn cung cấp một dòng mới, nhưng nếu không thì bảo toàn đầu vào.

  • read sẽ không bao giờ cung cấp một dòng mới, và sẽ diễn giải các chuỗi dấu gạch chéo ngược.

Ngoài ra, readcó các tùy chọn bổ sung, chẳng hạn như chia tách, hết thời gian và lịch sử đầu vào, một số trong số đó là tiêu chuẩn và các tùy chọn khác giữa các shell.


Cảm ơn. Những khác biệt về hành vi là những gì tôi đang tìm kiếm. Tôi cũng muốn biết rằng, như @ glenn-jackman đã chỉ ra, readcó thể phân tích các tham số được phân tách bằng dấu tách trường bên trong $IFS. straceThủ thuật của @ ramesh cũng là một cách tuyệt vời để phân tích sự khác biệt.
Tyler

5

Đối với một điều, bạn có thể phân tích văn bản bằng đọc, không chỉ mất toàn bộ một dòng

echo "foo:bar:baz" | {
  IFS=: read one two three
  echo $two
}

Bạn không phân tích nó với read, chính xác, bạn phân tích nó với $IFS. IFS=:; set -- ${0+foo:bar:baz}; echo "$2"hoàn thành tương tự - và nó không yêu cầu |pipeshoặc nhân bản con. Hoặc : IFS=:; printf %.0s%s%.0s\\n ${0+foo:bar:baz}. Khác: echo foo:bar:baz | { IFS=:; set -- $(cat); echo "$2"; }nếu bạn phải có đường ống. Trong mọi trường hợp, việc chia tách là kết quả của cài đặt của bạn $IFS; không nhất thiết là bạn read
mikeerv

2
Thật. readgán các phần tách cho các biến.
glenn jackman

5

Nội dung có mặt như một cách để hệ thống gọi nhanh hơn. Vì vậy, tôi tin rằng readlệnh có mặt như một nội dung để có hiệu quả hơn.

Trích dẫn từ đây ,

Các lệnh dựng sẵn này là một phần của shell và được triển khai như một phần của mã nguồn của shell. Shell nhận ra rằng lệnh mà nó được yêu cầu thực thi là một trong những nội trang của nó và nó tự thực hiện hành động đó mà không cần gọi ra một lệnh thực thi riêng. Các shell khác nhau có các nội trang khác nhau, mặc dù sẽ có rất nhiều sự chồng chéo trong bộ cơ bản.

Bây giờ, tôi muốn điều này được tự mình thử nghiệm, để bạn có thể hiểu tại sao lại readcó mặt dưới dạng vỏ.

Thông thường, bạn không thể làm stracetrên các nội trang. Tuy nhiên, có một cách giải quyết cho điều này là tốt. Điều này được giải thích khá gọn gàng trong câu trả lời này .

  1. Trong shell đầu tiên, chạy lệnh như stty -echo.
  2. Mở một shell khác và chạy lệnh như cat | strace bash > /dev/null.
  3. Bây giờ, shell sẽ chờ người dùng gõ các lệnh và ở đó khi người dùng gõ các lệnh, bạn cũng có thể thấy những gì xảy ra ở cấp hệ thống.
  4. Khi bạn đưa ra 3 lệnh trên, bạn có thể thấy rằng đọc có ít lệnh gọi hệ thống hơn 2 lệnh còn lại. Tôi không dán đầu ra từ stracevì nó là khá lớn.

1
Ngoài ra các readnội dung trong /bin/shtiền tồn tại headvà có lẽ sed.
Perry

1
tl; dr: readlà một nội dung tích hợp và bỏ qua chi phí và sổ sách kế toán liên quan đến việc bắt đầu một quy trình mới.
Henk Langeveld

0

Bạn có thể sử dụng varnamechỉ đọc bên trong tập lệnh shell nhưng hai tập lệnh khác bạn có thể sử dụng mà không cần viết tập lệnh shell.

Ví dụ:

Bạn có thể sử dụng varname=$(head -1)varname=$(sed 1q)chỉ đơn giản là một lệnh trong thiết bị đầu cuối, nhưng bạn phải cung cấp đối số của mình, tức là tập tin nào trên cùng mà bạn đang đề cập đến varnam=$(head -1 file1).


2
Tất nhiên bạn có thể sử dụng read varnamebên ngoài một kịch bản shell. Thử nó! Có rất ít điều bạn có thể làm trong một kịch bản mà bạn không thể thực hiện tại một dấu nhắc trong họ shell "sh" (cho dù chúng rất hữu ích là một vấn đề khác).
Perry
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.