Bagaimana cara membaca beberapa baris dari STDIN ke dalam variabel?


24

Saya sudah googling pertanyaan ini tidak berhasil. Saya mengotomatiskan proses pembuatan di sini di tempat kerja, dan semua yang saya coba lakukan adalah mendapatkan nomor versi dan deskripsi kecil dari bangunan yang mungkin multi-line. Sistem yang digunakan ini adalah OSX 10.6.8.

Saya telah melihat semuanya mulai dari menggunakan CAT hingga memproses setiap baris seperlunya. Saya tidak tahu apa yang harus saya gunakan dan mengapa.

Mencoba

read -d '' versionNotes

Menghasilkan input yang kacau jika pengguna harus menggunakan kunci backspace. Juga tidak ada cara yang baik untuk menghentikan input karena ^ D tidak berhenti dan ^ C hanya keluar dari proses.

read -d 'END' versionNotes

Berfungsi ... tetapi input input masih rusak jika tombol backspace diperlukan.

while read versionNotes
do
  echo "  $versionNotes" >> "source/application.yml"
done

Tidak mengakhiri input dengan benar (karena saya terlambat mencari yang cocok dengan string kosong).


Anda mendapatkan informasi ini dari pengguna, benar?
glenn jackman

Benar; Saya ingin pengguna memasukkan informasi ini di terminal ketika menjalankan skrip.
Robert K

1
Anda belum membuat diri Anda jelas, saya lebih suka mengatakan.
poige

Jawaban:


20

man bash menyebutkan «...

Substitusi perintah $ (file cat) dapat diganti dengan yang setara tetapi lebih cepat $ (<file).

... »

$ myVar=$(</dev/stdin)
hello
this is test
$ echo $myVar
hello this is test
$ echo "$myVar"
hello
this is test

dan saya setuju ini layak disebut - echo "$myVar"akan menampilkan input seperti yang diberikan.


1
Bagaimana cara berhenti setelah input multiline? Jika saya menekan Ctrl C berhenti tetapi variabel tidak disimpan!
Nikhil

2
Terminal UNIX® memiliki "disiplin": en.wikipedia.org/wiki/Line_discipline • Periksa apa artinya "eof" • Bacalah man stty, cari tahu bagaimana mendapatkan pengaturan saat ini
poige

2
ctrl-d untuk berhenti.
freb

9

Coba ini:

user@host:~$ read -d '' x <<EOF
> mic
> check
> one
> two
> EOF

Tanpa jeda baris:

user@host:~$ echo $x
mic check one two

Dengan jeda baris:

user@host:~$ echo "$x"
mic
check
one
two

2
-d ''persis apa yang saya butuhkan. Terima kasih
Bruno Bronosky

@Bruno Dengan senang hati; itu rumit. Terutama pada pandangan pertama, tampilannya cukup standar. Namun bisa sangat berguna, setelah Anda memahami berbagai keanehan.
Suara


2

Saya telah memecahkan masalah ini dengan menangani setiap baris sampai saya menemukan baris kosong. Ini cukup berhasil untuk situasi saya. Tetapi jika seseorang ingin menambahkan solusi yang lebih baik, jangan ragu untuk melakukannya.

echo "---
notes: |" > 'version.yml'

while read line
do
  # break if the line is empty
  [ -z "$line" ] && break
  echo "  $line" >> "source/application.yml"
done

Gunakan read -rsebagai gantinya.
adaptr

2

Anda dapat memulai editor seperti vim, pico ...

${VISUAL:-${EDITOR:-vi}} source/application.yml

Um ... bagaimana itu menjawab pertanyaan OP dengan cara apa pun?
adaptr

Dia dapat memulai editor dari skrip.
Mircea Vutcovici

Dan itu mencapai apa, tepatnya? Dia ingin menggunakan teks dari file dalam skrip, bukan menulis informasi ke file.
adaptr

Dia tidak dapat membaca teks dari pengguna dan menulisnya ke file. Silakan baca komentar yang ditambahkan ke pertanyaan.
Mircea Vutcovici

1

Pertama beberapa koreksi:

  1. Untuk mengizinkan "edisi" pada penggunaan baris -eyang menggunakan readline (sehingga Anda memiliki riwayat bash dan semua fitur pengeditan)
  2. -dhanya membutuhkan satu karakter. Misal dari 'END' mengambil 'E' dan setiap kali pengguna menulis 'E' pembacaan berhenti (saya kira itu bukan yang Anda inginkan ...)

Ada beberapa kemungkinan untuk melakukan ini. Saya akan membaca baris demi baris dan berhenti ketika baris kosong ditemukan (meskipun Anda dapat menyetel kata berhenti):

unset tmp
while :
do 
 read line
 [[ $line == "" ]] && tmp="${tmp:0:$((${#tmp}-1))}" && break
 tmp="$tmp"$line$'\n'
done

0

Anda memiliki beberapa metode.

Salah satu metode paling sederhana adalah:

MYVAR=$(yourcommand)
echo $"MYVAR"

Sebagai contoh:

MYVAR=$(ls /)
echo $"MYVAR"

Kecuali saya tidak menjalankan perintah shell seperti LS. Saya meminta input multi-line dari pengguna.
Robert K

Ini adalah praktik yang sangat buruk; jangan memproses output ls!
adaptr

@adaptr Kami telah mendengar semuanya sebelumnya, maukah Anda menyarankan alternatif yang baik?
Suara

0

Kami menggunakan konstruksi menggunakan xargs dan ctrl-d untuk memecah. Saya tidak sepenuhnya puas dengan itu, tetapi tentu saja pekerjaan mengambil input multi-line pengguna dan memasukkannya ke dalam variabel (format utuh). (Tugas pertama dan ketiga menambahkan tanda kutip di sekitar isi input xargs.)

    printf "\\033[1mWhen finished hit ctrl-d on a new line to proceed.\\033[0m  \\n\\n" 
    # this will load the user's input into a variable instead of a file 
    reminderBody="\"" 
    reminderBody+=$( xargs -0 ) 
    reminderBody+="\"" 

Kami menggunakan reminderBody sebagai subjek email yang dikirim melalui surat (via bash).


-1

Lihat: http://tldp.org/LDP/abs/html/internal.html#READR

Gunakan readdan perhatikan bahwa jika Anda mengakhiri baris dengan \baris baru diabaikan. Jadi Anda bisa melakukan:

#! / bin / bash

baca -p "versi:" versi
echo $ version

# masukkan beberapa input dan akhiri baris panjang dengan "\", lalu masukkan polos di akhir
baca -p "deskripsi:" deskripsi
echo -e "$ version \ n $ description >> yourfile.txt

Jika saya hanya ingin paragraf dengan jeda baris diabaikan, ya. Tetapi karena ini adalah daftar catatan rilis yang dihasilkan untuk skrip build, saya harus dapat mempertahankan jeda baris tersebut; Saya mungkin mencoba memasukkan daftar berpoin, misalnya.
Robert K

ABS adalah keburukan proporsi mengerikan. 90% dari itu jelas salah.
adaptr

Ini bukan yang buruk.
Suara
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.