Mengotomatiskan input tekstual dari skrip bash tanpa menggunakan EOF

10

Saya menjalankan Ubuntu Linux. Misalkan ada program yang disebut myprogram. Program ini meminta input dari pengguna; khusus, pengguna harus mengetik bilangan bulat ketika diminta dan tekan Enter. Saya ingin mengotomatiskan proses ini menggunakan skrip bash. Secara khusus, saya ingin mengeksekusi myprogram, katakanlah, 100 kali (menggunakan penghitung iyang beralih dari 1ke 100). Pada setiap eksekusi myprogram, saya ingin memasukkan nilai saat ini iketika diminta.

(Omong-omong, myprogrammengambil opsi / switch -options, yang semuanya akan konstan dan dengan demikian ditentukan dalam skrip bash.)

Kerangka skrip bash yang tidak lengkap ini mungkin:

#!/bin/bash
for i in {1..100}
do
   myprogram -options
done

Sekarang saya ingin memodifikasi kode di atas sehingga nilai saat iini dimasukkan ketika diminta oleh program. Apa cara terbaik untuk melakukan ini?

Situs web perangkat lunak yang saya gunakan menyarankan penggunaan <<EOFdi akhir myprogram -optionsbaris. Saya pikir ini memberitahu bash untuk melihat "akhir file" untuk input yang akan digunakan. Tetapi bagaimana jika saya tidak ingin menempatkan input di akhir file? Bagaimana jika saya ingin meletakkannya segera setelah <<atau <?

Alasannya adalah bahwa hal-hal akan menjadi lebih rumit. Sebagai contoh, saya dapat memperkenalkan penghitung bilangan bulat jyang berubah dalam beberapa cara non-linear, non-sekuensial. Saya kemudian ingin memberi makan nilai saat ini juntuk myprogrampada setiap iterasi, tetapi nilai jdapat berubah antara panggilan ke myprogram -optionsdan akhir file EOF.

Apakah Anda punya saran?

Andrew
sumber
Lihat blog ini - Menjalankan Program interaktif
Suresh

Jawaban:

14

Untuk hampir semua program, keduanya echo $i | myprogram -optionsdan myprogram -options <<<$iharus bekerja, dengan memberi makan program $imelalui input standar.

<fooakan menggunakan isi file bernama foostdin.

<<fooakan menggunakan teks antara itu dan garis yang hanya terdiri dari fooinput standar. Ini adalah dokumen di sini (heredoc), seperti yang dikatakan Gilles; EOFsebenarnya bukan berarti akhir dari file, itu hanya delineator heredoc yang umum (kita menggunakan "foo" sebagai gantinya dalam contoh ini).

<<<fooakan menggunakan string "foo" sebagai input standar. Anda juga dapat menentukan variabel $foo, dan shell akan menggunakan isinya sebagai stdin, seperti yang saya tunjukkan di atas. Ini disebut herestring , karena menggunakan string pendek berbeda dengan seluruh blok, seperti dalam heredoc. Herestrings bekerja di bash, tetapi tidak di /bin/sh.

Kevin
sumber
9

Sintaks yang direkomendasikan oleh situs web ini disebut dokumen di sini . Input ke program file dimulai segera di bawah baris yang berisi <<EOF, dan itu tidak diakhiri pada akhir skrip, tetapi oleh baris yang berisi teks secara persis EOF(berhati-hatilah untuk tidak memiliki spasi tambahan). Omong-omong, Anda dapat menggunakan penanda akhir apa pun yang tidak mengandung karakter khusus shell: EOFbukan kata kunci, itu hanya tradisional.

#!/bin/bash
for i in {1..100}
do
   myprogram -options <<EOF
$i
EOF
   for j in {1..42}; do
     myprogram2 <<EOF
$i
$j
EOF
   done
done
Gilles 'SANGAT berhenti menjadi jahat'
sumber
dengan kata lain, EOF dalam konteks ini berarti penanda akhir file , bukan akhir sebenarnya dari file skrip. teks "EOF" adalah sembarang teks - apa pun yang Anda gunakan segera setelah << karakter akan menunjukkan akhir dari dokumen di sini-sekarang. Saya biasanya menggunakan EOF karena menonjol dan sangat tidak mungkin berada di dalam dokumen saat ini jika, misalnya, saya secara sistematis menghasilkan skrip shell (yang saya lakukan cukup sering).
cas
EOF yang dicetak tebal harus <underscore><underscore>EOF<underscore> <underscore>
cas
Menggunakan dokumen-dokumen di sini seperti ini, saya sering mengubah penanda akhir menjadi sesuatu yang jauh lebih bermakna (dan lebih kecil kemungkinannya untuk dicocokkan secara "acak"), misalnya END_OF_WHATEVER_FUNCTION. Terkadang, mencoba untuk "menghemat" ruang / ukuran sebenarnya merupakan usaha yang sia-sia karena menyebabkan ambiguitas tentang apa yang sebenarnya terjadi.
killermist
Bagaimana Anda sleepdi antara perintah membaca dari skrip?
boltup_im_coding
@ terduga62 Saya tidak mengerti apa yang Anda minta. Anda mungkin harus mengajukan pertanyaan baru di situs ini. Pastikan untuk memberikan konteks yang cukup.
Gilles 'SANGAT berhenti menjadi jahat'
3

di sini dokumen seperti yang disebutkan oleh Kevin dan Gilles di atas, atau perpipaan sederhana akan berfungsi dalam banyak kasus.

Untuk situasi yang lebih rumit, Anda mungkin ingin melihat Expect atau yang serupa (misalnya modul Expect :: Simple CPAN adalah implementasi perl yang sangat mudah digunakan). secara pribadi, saya lebih suka modul perl (Harapkan itu sendiri tcl) tetapi ada implementasi untuk banyak bahasa scripting umum. Bahkan mungkin untuk menulis implementasi ide yang sangat primitif di sh atau bash menggunakan saat dan membaca.

Gagasan umum Expect dan alat-alat serupa adalah menunggu string atau pola yang ditentukan dalam output suatu program, dan kemudian mengumpankannya input apa pun yang Anda inginkan.

Contoh umum yang digunakan adalah mengotomatiskan login, dengan "mengharapkan" (yaitu menunggu) string "ogin:", mengirim nama login, lalu mengharapkan string "kata:" dan mengirim kata sandi.

Satu opsi terakhir, jika Anda memiliki sumber myprogram, adalah memodifikasinya untuk mengambil input yang ingin Anda berikan sebagai opsi baris perintah. Ini mungkin sedikit lebih banyak bekerja di muka, tetapi akan jauh lebih memberatkan daripada bermain-main dengan Expect atau memipipkan data ke dalam program yang tidak dirancang untuk digunakan dengan cara itu.

... dan jangan lupa untuk mengirimkan tambalan Anda ke myprogram kembali hulu :) Bahkan jika mereka tidak suka cara Anda mengkodekannya, mereka mungkin cukup menyukai ide untuk menambahkan fitur itu sendiri. Pengembang hulu cenderung menghargai orang-orang yang keluar dari pantat mereka dan berkontribusi daripada menuntut atau mengeluh.

cas
sumber