grep "hehe" < test.sh
Chuyển hướng đầu vào - chỉ hoạt động cho một tệp duy nhất, tất nhiên, trong khi cat
hoạt động với bất kỳ số lượng tệp đầu vào nào.
Cân nhắc các ký hiệu:
grep "hehe" $(cat test.sh)
grep "hehe" `cat test.sh`
Đây là tương đương trong bối cảnh này; nó là dễ dàng hơn để sử dụng '$(cmd)
' ký hiệu trong sử dụng lồng nhau, chẳng hạn như:
x=$(dirname $(dirname $(which gcc)))
x=`dirname \`dirname \\\`which gcc\\\`\``
(này cung cấp cho bạn các thư mục cơ sở, trong đó GCC được cài đặt, trong trường hợp bạn đang tự hỏi.)
Trong ví dụ grep
, điều xảy ra là nội dung của test.sh
được đọc và chia thành các từ được phân tách bằng dấu cách trắng và mỗi từ như vậy được cung cấp dưới dạng đối số cho grep
. Vì grep
xử lý các từ sau "hehe"
(trong đó grep
, tất nhiên, không không xem dấu ngoặc kép - và chúng không cần thiết trong trường hợp này, như một quy tắc chung, sử dụng dấu nháy đơn chứ không phải dấu ngoặc kép, đặc biệt là xung quanh các chuỗi phức tạp như cụm từ thông dụng thường sử dụng các siêu ký tự shell) ... Như tôi đã nói, grep
xử lý các từ sau "hehe"
làm tên tệp và cố gắng mở từng tệp, thường không thất bại do tệp không tồn tại. Đây là lý do tại sao ký pháp không phù hợp trong ngữ cảnh này.
Sau khi xem lại câu hỏi, có thể nói nhiều hơn - điều đó chưa được nói.
Trước hết, nhiều lệnh Unix được thiết kế để hoạt động như 'bộ lọc'; họ đọc đầu vào từ một số tệp, chuyển đổi nó theo một cách nào đó và ghi kết quả vào đầu ra tiêu chuẩn. Các lệnh như vậy được thiết kế để sử dụng trong các đường dẫn lệnh. Ví dụ như:
- mèo
- grep
- troff và người thân
- awk (với hãy cẩn thận)
- sed
- loại
Tất cả các bộ lọc này có hành vi chung giống nhau : họ có các tùy chọn dòng lệnh để kiểm soát hành vi của họ và sau đó họ đọc tệp s được chỉ định làm đối số dòng lệnh hoặc, nếu không có đối số như vậy, chúng sẽ đọc đầu vào chuẩn của chúng. Một số (như sort
) có thể có các tùy chọn để kiểm soát nơi đầu ra của chúng đi thay vì đầu ra tiêu chuẩn, nhưng điều đó tương đối không phổ biến.
Có một vài bộ lọc tinh khiết - tr
là một bộ lọc như vậy - đầu vào tiêu chuẩn đọc kỹ và ghi vào đầu ra tiêu chuẩn.
Các lệnh khác có các hành vi khác nhau. Eric Raymond cung cấp phân loại cho các loại lệnh trong "The Art of UNIX Programming".
Một số lệnh tạo danh sách tên tệp trên đầu ra tiêu chuẩn - hai tác phẩm kinh điển là ls
và find
.
Đôi khi, bạn muốn áp dụng đầu ra từ trình tạo tên tệp làm đối số dòng lệnh cho bộ lọc. Có một chương trình tự động thực hiện - đó là xargs
.
cổ điển, bạn sẽ sử dụng:
find . -name '*.[chyl]' | xargs grep -n magic_name /dev/null
Điều này sẽ tạo ra một danh sách đầy đủ các tập tin với phần mở rộng '.c
', '.h
', '.y
' và '.l
' (nguồn C, tiêu đề, Yacc và các tệp Lex). Vì danh sách được đọc bởi xargs
, nó sẽ tạo các dòng lệnh với grep -n magic_name /dev/null
khi bắt đầu và mỗi từ (được phân tách bằng dấu cách trắng) làm đối số.
Trong những ngày cũ, tên tệp Unix không bao gồm dấu cách. Dưới ảnh hưởng của Mac và Windows, các không gian như vậy giờ đã trở nên phổ biến. Các phiên bản GNU của find
và xargs
có các tùy chọn bổ sung để đối phó với vấn đề này:
find . -name '*.[chyl]' -print0 | xargs -0 grep -n magic_name /dev/null
Các '-print0
' tùy chọn có nghĩa là "tên file in chấm dứt bởi một NUL '\ 0'" (vì các nhân vật duy nhất có thể không xuất hiện trong một tên tập tin (đơn giản) là '/' và NUL, và rõ ràng, '/' có thể xuất hiện trong tên đường dẫn). Tương ứng '-0
' yêu cầu xargs
tìm tên được chấm dứt bằng NUL thay vì tên cách nhau bằng dấu cách.
Câu hỏi của bạn hơi khó hiểu - hy vọng chuyển hướng đầu vào hoặc chỉ đơn giản là cung cấp tên tệp làm đối số là những gì bạn muốn. Mặt khác, nếu bạn đang hỏi làm thế nào để có được stdout của một lệnh và đưa nó vào stdin của lệnh khác mà không cần sử dụng một đường ống ... đó là định nghĩa của một đường ống. – Cascabel