Bagaimana saya bisa mengirim karakter ke perintah seolah-olah mereka berasal dari file?

22

Bagaimana saya bisa mengirim karakter ke perintah seolah-olah mereka berasal dari file?

Misalnya saya mencoba:

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

Jawaban:

32

Dalam shell yang mendukung string di sini , termasuk bash, zshdan ksh93, Anda dapat menggunakan

wc <<< "apple pear orange"
Steeldriver
sumber
@ Kusalananda terima kasih - Saya mengedit info Anda di
steeldriver
18

Dua pendekatan lain (yang memungkinkan input berganda tanpa usaha ekstra):

  1. Gunakan "di sini dokumen":

    $ wc << EOF
    apel apel oranye
    EOF
      1 3 18
    $

    The EOFstring pembatas. Anda dapat menggunakan string apa pun; EOFhanyalah pilihan konvensional.

  2. Gunakan tty sebagai input:

    $ wc
    apel apel oranye
    Ctrl+D
      1 3 18
    $

    Ini memiliki kelemahan bahwa program mulai berjalan, dan mulai membaca input, segera setelah Anda mengetik namanya. Ini bisa membingungkan; sebagai contoh:

    $ grep v
    Rubah cokelat cepat              (diketik) 
    melompati                       (diketik) 
    melompati                       (Ini adalah keluaran dari grep!) 
    Anjing malas.                   (diketik)
    Ctrl + D
                                    (Tidak ada keluaran di sini) 
    $
G-Man Mengatakan 'Reinstate Monica'
sumber
Sebagai catatan: <<<Formulir ini juga memungkinkan input beberapa baris tanpa usaha ekstra, karena "string-tertutup dapat berisi baris baru. Tentu saja << EOFformulir (sintaksis sini-doc asli) lebih mudah dibaca jika Anda memiliki input multi-line.
alexis
Halaman manual mengatakan bahwa di sini sintaksis string adalah <<< word- tentu saja, dalam konteks shell, a worddapat berupa string yang dikutip, berisi spasi dan baris baru! Doh! Itu sangat jelas sehingga tidak perlu dikatakan (dan, pada kenyataannya, saya tidak melihatnya disebutkan di halaman manual sama sekali). :-( Terima kasih telah menunjukkan ini kepada saya!
G-Man Mengatakan 'Reinstate Monica'
Saya tidak akan menyebutnya sederhana atau jelas, sungguh. A worddidefinisikan dalam halaman manual sebagai "Urutan karakter yang dianggap sebagai satu unit oleh shell" (alias "token"), dan Anda perlu tahu bahwa string yang dikutip diperlakukan sebagai "unit tunggal" dalam arti yang relevan (setelah pemrosesan backslash, ekspansi variabel, dll. "Tetapi memang itulah tujuan dari double-quoting di shell. (Kutipan tunggal juga melindungi dari ekspansi.) Model pemrosesan shell dipikirkan dengan sangat baik, dan apa pun kecuali hal sederhana.
alexis
@alexis: Ketika saya pergi ke atas seperti itu dan memasukkan emotikon, orang harus mempertimbangkan kemungkinan bahwa saya menjadi ironis.
G-Man Mengatakan 'Reinstate Monica'
10

Meskipun ada beberapa solusi yang valid di sini, sintaks lain yang terkadang bermanfaat, adalah menjalankan perintah <(). Ini akan memungkinkan Anda untuk membuat lebih dari 1 objek file-deskriptor pada baris perintah.

Ini bisa berguna ketika Anda melakukan sesuatu seperti membandingkan string teks yang panjang, atau jika Anda ingin membedakan beberapa konten yang tidak ada dalam file.

Misalnya, membandingkan file host pada dua node tanpa harus menyalin file host ke localhost:

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

The <pengalihan file untuk STDIN, dan ()membuat subkulit untuk menjalankan perintah antara kurung. Ini adalah STDOUT dari subkulit yang diteruskan ke STDIN dari perintah yang sedang dijalankan.

Ini adalah cara yang lebih mudah untuk membuat lebih dari 1 input "file" ke suatu perintah daripada mencoba menggunakan banyak dokumen di sini, atau mencoba untuk menggemakan beberapa perintah ke dalam sebuah pipa ke perintah terakhir.

Tim Kennedy
sumber
<fileorpathnamearahan ulang stdin, tetapi <(subcmd)tidak; itu mengganti nama yang ketika / jika dibuka oleh program dapat membaca stdout dari subcmd. < <(subcmd)(diperlukan ruang) melakukan redirect stdin dari file itu, hampir seperti subcmd |. Anda diffdapat membaca salah satu inputnya dari stdin dengan menentukan argumen -tetapi tidak keduanya.
dave_thompson_085
Itu adalah proses substitusi yang tidak didukung, tidak seperti bagian yang Anda klaim dibuat (tapi tidak seperti yang dijelaskan dave).
phk
1
Diff saya berfungsi dengan baik di bash pada Ubuntu 16.04, dan sistem Solaris 11.2 yang harus saya uji. Mungkin saja itu tidak berfungsi untuk semua shell pada semua sistem operasi. Ini sebenarnya membuat deskriptor file yang dapat digunakan untuk membaca output dari subproses seolah-olah sedang membaca file. Karena diff mengambil dua argumen file, ia dapat membaca output dari kedua subproses melalui deskriptor file yang dibuat, dan membandingkannya.
Tim Kennedy
Anda mungkin ingin menambahkan jawaban Anda perbedaan antara cmd <(cmd2 ...)dan cmd < <(cmd2 ...). Yang pertama memungkinkan data yang diturunkan (output dari cmd2) untuk digunakan di tempat nama file. Yang terakhir ini setara dengan cmd2 ... | cmd. Perintah harus ditulis untuk secara eksplisit menerima input stdin dan banyak yang tidak. Ini terutama berlaku untuk skrip shell.
DocSalvager
8

Anda bisa menggunakan pipa

echo "apple pear orange" | wc
Slh47
sumber
8
Suatu pipa tidak sama dengan "membaca dari file". Misalnya Anda tidak dapat mencari mundur dalam pipa, sedangkan Anda bisa dalam file.
rbialon
0

Anda mungkin ingin menggunakan sesuatu yang mirip dengan yang diharapkan. Berikut ini adalah contoh sederhana dari membuka sesi telnet jarak jauh, menunggu konfirmasi, mengirim beberapa data, menunggu tanggapan, tidur dan keluar.

#!/usr/bin/expect
spawn telnet localhost 8555
expect "Escape character is '^]'."
send "Hello World\n"
expect "Connection closed by foreign host."
sleep 1
Pengecut Anonim
sumber