Kirim teks ke program yang mengharapkan file

30

Terkait dengan pertanyaan yang saya ajukan di Stack Overflow: Melewati beberapa baris kode ke wsadmin.sh? .

Saya memiliki, sebagai string, beberapa baris input yang perlu saya masukkan ke dalam perintah. Namun, perintahnya hanya menerima file yang penuh dengan input.

Apakah ada cara saya bisa menyimpan baris dalam file atau pipa sementara yang tidak pernah benar-benar ditulis ke disk dan kemudian memasukkannya langsung ke program?

Bagaimana cara saya mendapatkan pipa, memasukkan input ke dalamnya, melewati pipa itu ke perintah, dan kemudian menyingkirkan pipa?

ArtOfWarfare
sumber
2
Bisakah Anda menambahkan contoh perintah yang Anda gunakan, dan bagaimana perintah itu diminta?
Terobosan
2
Apakah itu berarti program tidak menerima stdin?
Léo Lam
Saya setuju dengan kedua komentator di atas. Tidak mungkin menyarankan apa pun yang dapat bekerja tanpa mengetahui spesifikasi program.
Larssend

Jawaban:

27

Solusi lain adalah dengan menggunakan Proses Substitusi di Bash. Jika sistem Anda memiliki nama pipa, Anda dapat menggunakan fitur ini.

Digunakan seperti ini:

program_expecting_a_file <(list)

di mana listurutan perintah shell (sebenarnya jaringan pipa; rincian lengkapnya ada di sini ). listakan dieksekusi, dan hasilnya akan terhubung ke pipa. Nama pipa kemudian diteruskan ke program Anda.

CATATAN: spasi tidak diizinkan antara <dan (.

(Substitusi lain >(list)juga berfungsi seperti yang Anda harapkan.)

Dalam kasus spesifik Anda , Anda dapat menggunakan

program_expecting_a_file <(echo "$your_strings")

meskipun Anda mungkin menemukan solusi @ meuh menjadi lebih elegan.

Pembaruan: Banyak sekali contoh penggunaan dapat ditemukan di Panduan Pembuatan Skrip Bash Lanjutan .

Edward
sumber
Dua lainnya tidak bekerja bahkan dalam kasus yang paling sepele. Anda lulus dari tes yang saya lakukan sejauh ini. Saya telah meningkatkan milik Anda untuk saat ini. Saya akan kembali dan menandai ini sebagai diterima jika itu melakukan semua yang saya butuhkan.
ArtOfWarfare
Milikmu bekerja dengan sempurna. Jika mau, Anda dapat menambahkannya ke pertanyaan terkait di StackOverflow dan saya dapat menerimanya di sana juga. stackoverflow.com/questions/31374202/…
ArtOfWarfare
Hai @ ArtOfWarfare, senang bisa membantu. Ada komentar di sana sudah dengan solusi yang diusulkan yang sama, jadi tidak tepat bagi saya untuk mengirim jawaban di sana.
Edward
Anda memposting solusi Anda sebelum dia melakukannya. Ngomong-ngomong, saya sudah memintanya untuk mengubah komentarnya menjadi jawaban sehingga saya bisa menerimanya. Jika kalian tidak memposting jawaban dalam ~ 24 jam pada pertanyaan itu, saya hanya akan memposting jawaban itu sendiri sehingga saya dapat menerimanya (saya tidak suka meninggalkan pertanyaan saya sebagai jawaban yang belum terjawab begitu saya menemukan jawabannya). hanya perilaku buruk bagi calon pembaca / calon penjawab pertanyaan.)
ArtOfWarfare
Hai @ ArtOfWarfare, saya baik-baik saja dengan apa yang Anda usulkan!
Edward
15

Anda dapat menggunakan bash di sini-doc . Sebagai contoh,

$ cat -n <<<'a
> b'
 1  a
 2  b

Jika Anda memiliki sesuatu dalam variabel bash, Anda juga dapat menginterpolasinya: mis <<<"path is $PATH".


Jika perintah Anda bersikeras nama file, Anda bisa memberikannya /dev/stdin. Misalnya:

$ sed -f /dev/stdin <<<'s/a/b/'

menghasilkan output: s/b/b/.

meuh
sumber
Tidak jelas dari pertanyaan apakah perintah menerima input stdin, dan jika tidak, ini tidak akan berhasil. Saya harap OP mengklarifikasi.
David Z
1
:( - Ini tampak sangat menjanjikan, tetapi ketika saya mencobanya, saya mendapat pesan kesalahan"-f" option must be followed by a file name.
ArtOfWarfare
Di sini-doc adalah untuk stdin. Jika perintah Anda benar-benar membutuhkan -fdan nama file, maka berikan nama file /dev/stdin. Lihat hasil edit saya.
meuh
Saya pikir setelah pengeditan itu benar-benar pilihan yang layak!
Edward
1
+1 untuk /dev/stdinsaran. Program yang saya coba panggil hanya menerima nama file, jadi saya telah dikombinasikan /dev/stdindengan heredoc.
Huw Walters
7

Bergantung pada apa yang ada di skrip, Anda mungkin dapat menggunakan nama file khusus - (minus) yang merupakan singkatan dari stdin

$ mycmd -
Line 1
Line 2
^D

Metode lain yang mungkin berfungsi untuk Anda adalah membuka file /dev/fd/0yang lagi-lagi singkatan dari stdin .

Opsi ketiga adalah membuat FIFO (First In First Out). Itu seperti file, tetapi memiliki dua ujungnya - Anda menulis di satu ujung dan membaca dari yang lain.

-- Process 1 --                  -- Process 2 --
$ mkfifo foo
$ cat foo
<waits>                          $ echo hello > foo
hello                            $
$ rm foo
Majenko
sumber
3
Mungkin perlu dicatat bahwa program harus ditulis untuk menginterpretasikan -dengan cara ini - ini bukan fitur dari shell atau sistem operasi. Meskipun tentu saja sebagian besar utilitas Linux standar mengikuti konvensi ini, sejauh yang saya tahu.
David Z
1
Nggak. Ini tidak berfungsi untuk program ini. Ada mode interaktif, tetapi saya ingin meneruskan perintah untuk dieksekusi ke program ini dari program lain, dan saya tidak ingin masuk ke lubang kelinci expect.
ArtOfWarfare
@ ArtOfWarfare Saya baru saja menambahkan opsi ketiga yang mungkin berfungsi.
Majenko
Jawaban bagus! Opsi kedua & ketiga pada dasarnya seperti <()solusi, tetapi lebih eksplisit - yang mungkin sangat berguna!
Edward
4

Ada pilihan lain yang mirip dengan mycmd -solusinya, tetapi bahkan untuk program yang tidak menangani -secara khusus:

$ mycmd /dev/stdin
Line 1
Line 2
^D

/dev/stdin tampaknya terkait dengan OS dan berfungsi untuk saya di Debian GNU / Linux, tapi saya tidak yakin di mana lagi itu akan berfungsi juga.

Axel Beckert
sumber
1
Sepertinya ini mungkin berhasil, tetapi apa itu ^D?
ArtOfWarfare
^Dadalah notasi umum untuk menekan Ctrl-D. ^ D memiliki semantik "end of input stream" di sini. Ini mungkin lebih sering terlihat di ^Catau ^Zyang berdiri untuk menekan Ctrl-C masing-masing untuk menekan Ctrl-Z.
Axel Beckert
1
Itu tampaknya berhasil, tetapi bagaimana saya secara program memasukkan barang ke dalam /dev/stdindan kemudian menutupnya?
ArtOfWarfare
1
Hanya pipa sesuatu ke perintah itu dan itu harus berfungsi, yaitu cat content | mycmd /dev/stdin. Bayangkan saja berbagai perintah dari catsini.
Axel Beckert