Làm thế nào tôi có thể gửi các ký tự đến một lệnh như thể chúng đến từ một tệp?


22

Làm thế nào tôi có thể gửi các ký tự đến một lệnh như thể chúng đến từ một tệp?

Ví dụ tôi đã thử:

wc < "apple pear orange"
-bash: apple pear orange: No such file or directory

Câu trả lời:


32

Trong các shell hỗ trợ ở đây các chuỗi , bao gồm bash, zshksh93, bạn có thể sử dụng

wc <<< "apple pear orange"

@Kusalananda cảm ơn - Tôi đã chỉnh sửa thông tin của bạn trong
Steeldo

18

Hai cách tiếp cận khác (cho phép nhập nhiều dòng mà không cần nỗ lực thêm):

  1. Sử dụng "tài liệu ở đây":

    $ wc << EOF
    táo lê cam
    EOF
      1 3 18
    $

    Các EOFchuỗi là một dấu phân cách. Bạn có thể sử dụng bất kỳ chuỗi nào; EOFchỉ là một sự lựa chọn thông thường.

  2. Sử dụng tty làm đầu vào:

    $ wc
    táo lê cam
    Ctrl+D
      1 3 18
    $

    Điều này có nhược điểm là chương trình bắt đầu chạy và bắt đầu đọc đầu vào, ngay khi bạn nhập tên của nó. Điều này có thể gây bối rối; ví dụ:

    $ grep v
    Con cáo nâu nhanh              (đánh máy) 
    nhảy qua                       (đánh máy) 
    nhảy qua                       (Đây là đầu ra từ grep!) 
    Con chó lười.                   (đã gõ)
    Ctrl + D
                                    (Không có đầu ra ở đây) 
    $

Đối với bản ghi: Biểu <<<mẫu cũng cho phép nhập nhiều dòng mà không cần nỗ lực thêm, vì "chuỗi ký tự có thể chứa dòng mới. Tất nhiên, << EOFbiểu mẫu (cú pháp tài liệu gốc ở đây) dễ đọc hơn nếu bạn có đầu vào nhiều dòng.
alexis

Trang man nói rằng cú pháp chuỗi ở đây là <<< word- tất nhiên, trong ngữ cảnh của shell, a wordcó thể là một chuỗi được trích dẫn, chứa khoảng trắng và dòng mới! Ôi! Điều đó quá rõ ràng đến nỗi không cần phải nói (và trên thực tế, tôi không thấy nó được đề cập trong trang người đàn ông nào cả). :-( Cảm ơn bạn đã chỉ ra điều này cho tôi!
G-Man nói 'Phục hồi Monica'

Tôi sẽ không gọi nó là đơn giản hoặc rõ ràng, thực sự. A wordđược định nghĩa trong trang này là "Một chuỗi các ký tự được coi là một đơn vị theo vỏ" (còn gọi là "mã thông báo") và bạn cần biết rằng các chuỗi được trích dẫn được coi là "một đơn vị" theo nghĩa liên quan (sau xử lý dấu gạch chéo ngược, mở rộng biến, v.v. "Nhưng thực sự đó là toàn bộ mục đích của trích dẫn kép trong shell. (Dấu ngoặc đơn cũng bảo vệ khỏi sự mở rộng.) Mô hình xử lý của shell được suy nghĩ rất kỹ, và bất cứ điều gì ngoài đơn giản.
alexis

@alexis: Khi tôi đi trên đỉnh như thế bao gồm một biểu tượng cảm xúc, người ta nên xem xét khả năng tôi đang mỉa mai.
G-Man nói 'Phục hồi Monica'

10

Mặc dù có một số giải pháp hợp lệ ở đây, đôi khi một cú pháp khác có thể hữu ích, là chạy một lệnh trong <(). Điều này sẽ cho phép bạn tạo nhiều hơn 1 đối tượng mô tả tệp trên một dòng lệnh.

Điều này có thể hữu ích khi bạn đang làm một cái gì đó như so sánh các chuỗi văn bản dài hoặc nếu bạn muốn tìm một số nội dung không có trong một tệp.

Ví dụ: so sánh các tệp máy chủ trên hai nút mà không phải sao chép tệp máy chủ vào localhost:

diff -Naur <(cat /etc/hosts) <(ssh -q otherhost 'cat /etc/hosts')

Các <chuyển hướng một tập tin vào STDIN, và ()tạo ra một subshell để chạy các lệnh giữa dấu ngoặc. Đó là STDOUT từ lớp con được truyền đến STDIN của lệnh đang được chạy.

Đó là một cách dễ dàng hơn để tạo nhiều hơn 1 "tệp" đầu vào cho một lệnh hơn là cố gắng sử dụng nhiều tài liệu ở đây hoặc cố gắng lặp lại nhiều lệnh thành một đường dẫn đến lệnh cuối cùng.


<fileorpathnamechuyển hướng stdin, nhưng <(subcmd)không; nó thay thế một tên mà khi / nếu được mở bởi chương trình có thể đọc thiết bị xuất chuẩn từ subcmd. < <(subcmd)(không gian cần thiết) không chuyển hướng stdin từ tệp đó, gần giống như subcmd |. Bạn diffcó thể đọc một trong những đầu vào của nó từ stdin bằng cách chỉ định một đối số -nhưng không phải cả hai.
dave_thndry_085

Đó là quá trình thay thế không được hỗ trợ, không giống như các phần bạn cho rằng nó được thực hiện (nhưng nó không được giải thích như vậy).
phk

1
Khác biệt của tôi hoạt động tốt trong bash trên Ubuntu 16.04 và các hệ thống Solaris 11.2 mà tôi phải thử nghiệm. Có thể nó không hoạt động cho tất cả các shell trên tất cả các hệ điều hành. Nó thực sự tạo ra các mô tả tệp có thể được sử dụng để đọc đầu ra từ quy trình con như thể nó đang đọc một tệp. Vì diff lấy hai đối số tệp, nó có thể đọc đầu ra của cả hai quy trình con thông qua các bộ mô tả tệp được tạo và so sánh chúng.
Tim Kennedy

Bạn có thể muốn thêm vào câu trả lời của bạn sự khác biệt giữa cmd <(cmd2 ...)cmd < <(cmd2 ...). Cái trước cho phép dữ liệu dẫn xuất (đầu ra của cmd2) được sử dụng để đặt tên tệp. Cái sau tương đương với cmd2 ... | cmd. Các lệnh phải được viết để chấp nhận đầu vào stdin một cách rõ ràng và nhiều lệnh thì không. Điều này đặc biệt đúng với các kịch bản shell.
DocSalvager

8

bạn có thể sử dụng một đường ống

echo "apple pear orange" | wc

8
Một ống ist không giống như "đọc từ một tập tin". Ví dụ, bạn không thể tìm kiếm ngược trong một đường ống, trong khi bạn có thể trong một tệp.
rbialon

0

Bạn có thể muốn sử dụng một cái gì đó tương tự như mong đợi. Sau đây là một ví dụ đơn giản về việc mở một phiên telnet từ xa, chờ lời nhắc, gửi một số dữ liệu, chờ phản hồi, ngủ và thoát.

#!/usr/bin/expect
spawn telnet localhost 8555
expect "Escape character is '^]'."
send "Hello World\n"
expect "Connection closed by foreign host."
sleep 1
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.