Tại sao dấu hiệu ít hơn không hoạt động như một sự thay thế cho con mèo trong bash?


17

Tôi đã nghe nói về "việc sử dụng mèo vô dụng" và tìm thấy một số gợi ý, nhưng những kết quả sau đây không có gì trong vỏ bash của tôi.

< filename

Sử dụng mèo làm việc như mong đợi mặc dù.

cat filename

Tôi đang sử dụng Fedora Core 18 và GNU bash, phiên bản 4.2.45 (1).

EDIT: Sử dụng nó trước một đường ống cũng không hoạt động.

< filename | grep pattern

Trong khi đó sử dụng mèo làm việc như mong đợi.

cat filename | grep pattern

EDIT2: Để làm rõ, tôi biết rằng tôi có thể sử dụng cái này

grep pattern < filename

nhưng tôi đọc ở đây /programming/11710552/usless-use-of-cat mà tôi cũng có thể sử dụng nó trước lệnh. Nó không hoạt động trước lệnh.


2
Nó hoạt động. Chỉ là những gì bạn đã thử không giống như nhận xét của Jonathan Leffler .
manatwork 20/12/13

"Mục đích của mèo là ghép các tệp (hoặc" catenate "). Nếu đó chỉ là một tệp, việc ghép nó không có gì là lãng phí thời gian và khiến bạn mất một quá trình." partmaps.org/era/unix/award.html
Bonsi Scott

Câu trả lời:


22

Ít hơn và ký hiệu ( <) đang mở tệp lên và gắn nó vào tay cầm thiết bị đầu vào tiêu chuẩn của một số ứng dụng / chương trình. Nhưng bạn đã không cung cấp cho bất kỳ ứng dụng nào để đính kèm đầu vào.

Thí dụ

Hai ví dụ này về cơ bản giống nhau nhưng nhận được đầu vào của chúng theo 2 cách khác nhau.

mở tập tin

$ cat blah.txt 
hi

mở STDIN

$ cat < blah.txt 
hi

Nhìn trộm đằng sau bức màn

Bạn có thể sử dụng straceđể xem những gì đang xảy ra.

Khi chúng tôi đọc từ một tập tin

open("blah.txt", O_RDONLY)              = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=3, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(3, "", 65536)                      = 0
close(3)                                = 0
close(1)                                = 0

Khi chúng tôi đọc từ STDIN (được xác định là 0)

read(0, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(0, "", 65536)                      = 0
close(0)                                = 0
close(1)                                = 0

Trong ví dụ đầu tiên, chúng ta có thể thấy rằng catđã mở tệp và đọc từ nó , blah.txt. Trong lần thứ hai, chúng ta có thể thấy rằng catđọc nội dung của tệp blah.txtthông qua bộ mô tả tệp STDIN, được xác định là số mô tả số 0.

read(0, "hi\n", 65536)                  = 3

1
Vì vậy, nói về việc sử dụng mèo vô dụng là không có thật?
lỗi

@ bọ - không, có công dụng. Nhưng catthường bị hiểu lầm và được sử dụng khi không cần thiết.
slm

Nhưng nó là cần thiết khi tôi muốn giữ trật tự của các hoạt động từ trái sang phải? Tôi đọc rằng có thể sử dụng cấu trúc ít hơn trước lệnh.
lỗi

@ bọ có, chuyển hướng có thể xảy ra trước hoặc sau lệnh, xem câu trả lời của Stephane, anh ta cũng hiển thị ví dụ này.
slm

Ah, bây giờ tôi hiểu rồi Tôi phải viết < filename command.
lỗi

14

Việc sử dụng vô dụng cổ điển catlà khi bạn sử dụng nó để cung cấp đầu vào cho các chương trình hoàn toàn có khả năng mở tệp trực tiếp. Ví dụ:

Xấu

cat file | grep foo
cat file | while read line; do echo "$line"; done
cat file | sed 's/a/b/'
cat file | awk '{print $1}'

Tốt

grep foo file
while read line; do echo "$line"; done < file 
sed 's/a/b/' file
awk '{print $1}' file

Cũng tốt ( <filecó thể ở hai bên của lệnh)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 

6
"Xấu" là chủ quan ở đây. Tôi thấy những cái đó là tốt hơn về tổng thể, bởi vì nó là cách phù hợp hơn và dễ đọc hơn. Và luồng dữ liệu hoàn toàn từ trái sang phải, như lẽ ra nếu có thêm các đường ống liên quan
Izkata

2
@Izkata họ "xấu" theo nghĩa là họ sử dụng vô dụng cat.
terdon

"Xuống! Xuống bàn đi! Bạn là một con mèo xấu! Nghiêng ;-) Nhưng nghiêm túc về vấn đề này
G-Man nói 'Tái lập lại' '

1
Đáng chú ý là sử dụng tốt (hoặc, ít nhất, hữu ích) catbao gồm (1) cat file(với đầu ra cho màn hình / thiết bị đầu cuối; mặc dù, nếu tệp dài hơn màn hình cao, bạn có thể thích sử dụng morehoặc đại loại lessnhư thế), (2) cat file1 file2 file3 > all_data( chính xác những gì catlà có nghĩa là cho), (3) cat f1 f2 f3 | tr …(hoặc ống vào bất kỳ chương trình khác mà bạn không muốn vượt qua các tập tin trực tiếp; ví dụ, wc(ví dụ, nếu bạn muốn xem tổng cộng chỉ) hoặc grep(ví dụ: nếu bạn có một phiên bản cũ không hỗ trợ -h, nghĩa là, --no-filename)), thì (Tiếp theo)
G-Man nói 'Tái lập lại' '

(Tiếp theo), (4) cat -n file | sort … -k1 | sed 's/^ *[0-9]*\t//', (5) sudo cat file600 | untrusted_program(nghĩa là bạn (UID của bạn) không thể đọc tệp và bạn không muốn chạy chương trình dưới dạng root hoặc thậm chí bất kỳ UID bán đặc quyền nào). Ngoài ra, ( e ) (tức là một số từ 2 đến 3) program_that_generates_html | cat static_html_header - static_html_footer(mà bạn có thể muốn chuyển hướng đến một tệp hoặc một đường ống).
G-Man nói 'Phục hồi Monica'

13

UUOC nằm trong:

cat somefile | some-cmd

hoặc là

cat < somefile | some-cmd

Ở đó, some-cmdđang đọc nội dung somefiletừ một đường ống được cho ăn catmà chính nó đọc nó từ đó somefile.

some-cmdcó thể đọc trực tiếp từ somefile(sau khi shell đã mở nó cho stdin), không cần cat:

some-cmd < somefile

hoặc là

< somefile some-cmd

(chuyển hướng có thể xuất hiện bất cứ nơi nào trên một dòng lệnh đơn giản).

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.