Birden fazla satırı STDIN'den bir değişkene nasıl okurum?


24

Bu soruyu boşuna gitmek için harcadım. Burada işyerinde bir derleme işlemini otomatik hale getiriyorum ve tek yapmaya çalıştığım sürüm numaralarını ve derlemenin çok satırlı olabileceği küçük bir tanımını almak. Bunun çalıştığı sistem OSX 10.6.8.

CAT'i kullanmaktan her çizgiyi gerektiği gibi işlemeye kadar her şeyi gördüm. Ne kullanmam gerektiğini ve neden kullanabileceğimi çözemiyorum.

Denemeler

read -d '' versionNotes

Kullanıcının geri silme tuşunu kullanması gerekiyorsa karışık girdiyle sonuçlanır. Ayrıca, girişi ^ D sona ermediği ve ^ C yalnızca işlemden çıktığı için sonlandırmanın iyi bir yolu yoktur.

read -d 'END' versionNotes

Çalışıyor ... ancak geri silme anahtarına ihtiyaç duyulursa girişi hala çalıyor.

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

Girişi düzgün bir şekilde sonlandırmıyor (çünkü boş bir dizeyle eşleşmeye bakmak için çok geç kaldım).


Bu bilgiyi kullanıcıdan alıyorsun, değil mi?
glenn jackman

Doğru; Komut dosyasını çalıştırırken kullanıcının bu bilgileri terminale girmesini istiyorum.
Robert K,

1
Kendini netleştirmedin, söylemeyi tercih ederim.
poige

Yanıtlar:


20

man bash bahseder «…

Komut ikame $ (cat file) eşdeğer fakat daha hızlı $ (<file) ile değiştirilebilir.

... »

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

ve bunun bahsetmeye değer olduğuna katılıyorum - echo "$myVar"girdiyi olduğu gibi gösterirdi.


1
Çok satırlı girişten sonra nasıl durulur? Ctrl C tuşlarına basarsam durur ancak değişken kaydedilmez!
Nikhil

2
UNIX® terminallerinin "disiplini" vardır: en.wikipedia.org/wiki/Line_discipline • "eof" ın ne anlama geldiğini kontrol edin • man stty
Okun,

2
Durdurmak için ctrl-d.
freb

9

Bunu dene:

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

Satır sonları olmadan :

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

İle satır sonları:

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

2
-d ''tam ihtiyacım olan şeydi. Teşekkürler
Bruno Bronosky

@ Bruno Benim zevkim; Bu zor bir tane. Özellikle ilk bakışta oldukça standart görünüyor. Yine de, çeşitli deyimlerden vazgeçtiğinizde oldukça faydalı olabilir.
dile


2

Boş bir çizgi bulana kadar her sorunu çözerek bu sorunu çözdüm. Durumum için yeterince iyi çalışıyor. Fakat eğer birisi daha iyi bir çözüm eklemek isterse, bunu yapmaktan çekinmeyin.

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

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

Yerine read -rkullanın.
adaptr

2

Vim, pico gibi bir editöre başlayabilirsiniz ...

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

Um ... bu OP'nin sorusuna nasıl bir cevap veriyor?
adaptr

Editöre senaryodan başlayabilir.
Mircea Vutcovici

Ve bu tam olarak ne başarır? O metni kullanmak isteyen dan , komut bir dosya değil yazma bilgi için bir dosya.
adaptr

Kullanıcıdan metin okumak ve bir dosyaya yazmak istiyordu. Lütfen soruya eklenen yorumları okuyun.
Mircea Vutcovici

1

İlk önce birkaç düzeltme:

  1. Satır üzerinde "basıma" izin vermek -eiçin readline kullanılır (böylece bash geçmişine ve tüm düzenleme özelliklerine sahip olursunuz)
  2. -dsadece bir karakter alır. Örneğin, 'SON' dan 'E' alır ve kullanıcı bir 'E' yazdığında okuma durur (Sanırım istediğin bu değil ...)

Bunu yapmak için birkaç imkan var. Satır satır okumaya gider ve boş bir satır bulunduğunda dururdum (herhangi bir durma sözcüğü ayarlasanız da):

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

0

Birkaç yönteminiz var.

En basit yöntemlerden biri:

MYVAR=$(yourcommand)
echo $"MYVAR"

Örneğin:

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

Dışında, LS gibi bir kabuk komutu çalıştırmıyorum. Kullanıcıdan çok satırlı giriş talep ediyorum.
Robert K,

Bu çok kötü bir uygulamadır; çıktısını işlemez ls!
adaptr

@adaptr Hepsini daha önce duyduk, iyi bir alternatif önerebilir misiniz, lütfen?
dile

0

Xargs ve ctrl-d kullanarak kırmak için bir yapı kullanıyoruz. Bundan tam anlamıyla memnun değilim, ama kesinlikle çok satırlı kullanıcı girişi alma ve bunu bir değişkene doldurma (bozulmamış biçimlendirme) işi yapıyor. (Birinci ve üçüncü ödevler, xargs girişinin içeriğine tırnak ekler.)

    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+="\"" 

HatırlatıcıBody'yi posta yoluyla (e-posta yoluyla) gönderilen bir e-postanın konusu olarak kullanıyoruz.


-1

Bakınız: http://tldp.org/LDP/abs/html/internal.html#READR

Kullanım readve bir çizgi sona eğer not \satırsonu dikkate alınmaz. Yani yapabilirsin:

#! / Bin / bash

-p "versiyon:" versiyonunu oku
echo $ version

# bazı girdiler girin ve "\" ile uzun satırları sonlandırın, ardından sonuna düz girin
-p "açıklama:" açıklamasını oku
echo -e "$ sürüm \ n $ açıklama >> yourfile.txt

Satır sonları göz ardı edilmiş bir paragraf istedim, evet. Ancak bu, bir derleme betiği için üretilmiş sürüm notları listesi olduğundan, bu satır sonlarını koruyabilmem gerekir; Örneğin, madde imli bir listeye girmeye çalışabilirim.
Robert K,

ABS, korkunç oranların canavarlığıdır. % 90'ı düz yanlış.
adaptr

O kadar da kötü değil .
dile
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.