Khi nào tôi nên sử dụng chuyển hướng đầu vào?


21

Tôi đã sử dụng hai lệnh sau để tạo ra kết quả giống nhau: -

[root@localhost ~]# grep line comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

[root@localhost ~]# grep line <comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

Có thể giải thích cho tôi bất kỳ ưu / nhược điểm nào nếu có bất kỳ 2 cách tiếp cận nào khác nhau.

Câu trả lời:


28

Từ man greptrang (trên Debian):

SỰ MIÊU TẢ

   grep  searches the named input FILEs (or standard input if no files are
   named, or if a single hyphen-minus (-) is given as file name) for lines
   containing  a  match to the given PATTERN.  By default, grep prints the
   matching lines.

Trong trường hợp đầu tiên, grepmở tệp; trong lần thứ hai, shell sẽ mở tệp và gán nó vào đầu vào tiêu chuẩn của grepgrepkhông được thông qua bất kỳ đối số tên tệp nào giả định rằng nó cần grep đầu vào tiêu chuẩn của nó.

Ưu điểm của 1:

  • grep có thể grep nhiều hơn một tập tin¹.
  • grepcó thể hiển thị tên tệp nơi mỗi lần xuất hiện lineđược tìm thấy.

Ưu điểm của 2:

  • Nếu tệp không thể được mở, trình bao trả về lỗi sẽ bao gồm nhiều thông tin liên quan hơn (như số dòng trong tập lệnh) và theo cách phù hợp hơn (nếu bạn cũng để trình bao mở tệp cho các lệnh khác) so với khi grepmở nó ra Và nếu tệp không thể được mở, grepthậm chí không được gọi (đối với một số lệnh - có thể không grep- có thể tạo ra sự khác biệt lớn).
  • trong grep line < in > out, nếu inkhông thể mở, outsẽ không được tạo hoặc cắt bớt.
  • Không có vấn đề gì với một số tệp có tên khác thường (tên -hoặc tên tệp bắt đầu bằng -) ².
  • mỹ phẩm: bạn có thể đặt <filebất cứ nơi nào trên dòng lệnh để hiển thị dòng lệnh một cách tự nhiên hơn, như <in grep line >outnếu bạn thích.
  • mỹ phẩm: với GNU grep, bạn có thể chọn nhãn nào sẽ sử dụng trước dòng phù hợp thay vì chỉ tên tệp như trong:

    <file grep --label='Found in file at line' -Hn line
    

Về mặt hiệu suất, nếu tệp không thể được mở, bạn lưu thực thi grepkhi sử dụng chuyển hướng, nhưng nếu không thì greptôi không mong đợi nhiều sự khác biệt.

Với tính năng chuyển hướng, bạn tiết kiệm được việc phải truyền thêm một đối số grep, bạn sẽ grepphân tích cú pháp đối số dễ dàng hơn một chút. Mặt khác, shell sẽ cần (ít nhất) một cuộc gọi hệ thống bổ sung đến dup2()bộ mô tả tệp vào bộ mô tả tệp 0.

Trong { grep -m1 line; next command; } < file, grep(ở đây GNU grep) sẽ muốn seek()quay lại ngay sau dòng phù hợp để next commandphần còn lại của tệp (nó cũng sẽ cần xác định xem tệp có thể tìm kiếm được hay không). Nói cách khác, vị trí trong stdin là một trong những grepđầu ra khác. Với grep -m1 line file, nó có thể tối ưu hóa điều đó, đó là một điều ít grepquan tâm hơn.


Ghi chú

Với zsh, bạn có thể làm:

grep line < file1 < file2

nhưng điều đó tương đương với cat file1 file2 | grep line(không gọi cattiện ích) và do đó kém hiệu quả hơn, có thể gây nhầm lẫn nếu tệp đầu tiên không kết thúc bằng ký tự dòng mới và sẽ không cho bạn biết mẫu nào được tìm thấy.

² Trong trường hợp ksh93bashmặc dù, có các tệp như /dev/tcp/host/port(và /dev/fd/xtrên một số hệ thống bash), khi được sử dụng trong mục tiêu chuyển hướng, shell chặn cho các mục đích đặc biệt thay vì thực sự mở tệp trên hệ thống tệp (mặc dù nói chung, các tệp đó không tồn tại trên hệ thống tập tin). /dev/stdinphục vụ cùng một mục đích như -được công nhận bởi grep, nhưng ít nhất, ở đây nó được đặt tên đúng hơn (bất kỳ ai cũng có thể tạo một tệp được gọi -trong bất kỳ thư mục nào, trong khi chỉ quản trị viên mới có thể tạo tệp được gọi /dev/tcp/host/portvà quản trị viên nên biết rõ hơn).


+1, cho lời giải thích tốt đẹp. Tôi có một nghi ngờ: trong trường hợp thứ 2 khi shell mở tệp thì nó có chuyển nội dung tệp đã mở sang đầu vào tiêu chuẩn (bàn phím) không ?? (Tôi đã nhầm lẫn với thuật ngữ 'đầu vào tiêu chuẩn của grep').
Ankit

1
@Ankit, stdin là nơi các ứng dụng đọc đầu vào của chúng theo mặc định, bộ mô tả tệp 0. Khi ở trong một thiết bị đầu cuối, fd 0 được mở từ việc đọc trên thiết bị đầu cuối (một cái gì đó như / dev / ttyxx hoặc / dev / pts / n). Đó là cách họ kết thúc với những gì bạn gõ trên bàn phím. Shell chuyển hướng của stdin của lệnh chỉ mở fd 0 sang một số tệp khác trước khi thực hiện lệnh.
Stéphane Chazelas

6

Câu trả lời của StephaneChazelas grep(1)và hầu hết các lệnh dòng Unix đều hoạt động theo cách đó, nhưng không phải tất cả. Đó là tiêu chuẩn để đọc từ đầu vào tiêu chuẩn (từ bàn phím, từ tệp được chuyển hướng qua < filehoặc từ đầu ra được dẫn bởi một lệnh khác, ví dụ ngu ngốc ls * | grep '^ab*c$') hoặc từ (các) tệp được cung cấp dưới dạng đối số, như grep comment file1 file2 file3. Một số lệnh sử dụng quy ước rằng tệp có tên -là đầu vào tiêu chuẩn, vì vậy bạn có thể nói make-middle | cat head - tailđể có một luồng với head, bất cứ thứ gì gen-middletạo ra, theo sau tail. Điều này là do thiết kế, để cung cấp sự linh hoạt trong việc sử dụng các lệnh.

Cái nào tốt hơn? Miễn là nó hoạt động, cmd filelà ngắn hơn cmd < file; có thể có một sự khác biệt nhỏ về thời gian giữa trình bao thực hiện tệp frobbing ( <) và lệnh tự thực hiện, nhưng có thể không được chú ý trừ khi bạn không làm gì khác cả ngày. Nó sẽ phụ thuộc vào những cân nhắc như những ưu điểm được đề cập trong câu trả lời của Stephane.


cmd filekhông phải là ngắn hơn cmd<filemặc dù.
Stéphane Chazelas 2/2/2016

Tuy nhiên, đó là một lần nhấn phím ngắn hơn, giả sử bạn cần nhấn Shift để nhập a <.
DopeGhoti
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.