it-swarm.com.de

Wie lese ich mehrere Zeilen von STDIN in eine Variable?

Ich habe diese Frage ohne Erfolg gegoogelt. Ich automatisiere hier bei der Arbeit einen Build-Prozess, und alles, was ich versuche, ist, Versionsnummern und eine winzige Beschreibung des Builds zu erhalten, die mehrzeilig sein kann. Das System, auf dem dies ausgeführt wird, ist OSX 10.6.8.

Ich habe alles gesehen, von der Verwendung von CAT bis zur Verarbeitung jeder Zeile nach Bedarf. Ich kann nicht herausfinden, was ich verwenden soll und warum.

Versuche

read -d '' versionNotes

Führt zu verstümmelten Eingaben, wenn der Benutzer die Rücktaste verwenden muss. Es gibt auch keine gute Möglichkeit, die Eingabe zu beenden, da ^ D nicht beendet wird und ^ C den Prozess nur beendet.

read -d 'END' versionNotes

Funktioniert ... aber die Eingabe wird immer noch verstümmelt, wenn die Rücktaste benötigt wird.

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

Beendet die Eingabe nicht richtig (weil ich zu spät bin, um nach Übereinstimmungen mit einer leeren Zeichenfolge zu suchen).

26
Robert K

man bash erwähnt "…

Die Befehlssubstitution $ (Cat-Datei) kann durch die entsprechende, aber schnellere $ (<Datei) ersetzt werden.

… "

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

und ich stimme zu, dass dies erwähnenswert ist - echo "$myVar" hätte die Eingabe so angezeigt, wie sie gegeben wurde.

21
poige

Versuchen Sie dies :

[email protected]:~$ read -d '' x <<EOF
> mic
> check
> one
> two
> EOF

Ohne Zeilenumbrüche :

[email protected]:~$ echo $x
mic check one two

Mit Zeilenumbrüchen :

[email protected]:~$ echo "$x"
mic
check
one
two
10
voices

Weitere Informationen zu Bash-Skripten finden Sie im ausgezeichneten Bash Guide .

Insbesondere der Bash FAQ enthält dies unter Nummer 1:

Wie kann ich eine Datei (Datenstrom, Variable) Zeile für Zeile (und/oder Feld für Feld) lesen?

8
adaptr

Sie können einen Editor wie vim, pico ...

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

Ich habe dieses Problem gelöst, indem ich mich mit jeder Zeile befasst habe, bis ich eine leere Zeile gefunden habe. Es funktioniert gut genug für meine Situation. Aber wenn jemand eine bessere Lösung hinzufügen möchte, können Sie dies gerne tun.

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

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

Zunächst einige Korrekturen:

  1. Um "Edition" in der Zeile zuzulassen, verwenden Sie -e, das readline verwendet (damit Sie den Bash-Verlauf und alle Bearbeitungsfunktionen haben)
  2. -d nimmt nur ein Zeichen an. Z.B. von 'END' nimmt 'E' und wenn der Benutzer ein 'E' schreibt, stoppt das Lesen (ich denke, das ist nicht das, was Sie wollen ...)

Hierfür gibt es einige Möglichkeiten. Ich würde Zeile für Zeile lesen und anhalten, wenn eine leere Zeile gefunden wird (obwohl Sie jedes Stoppwort festlegen könnten):

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

Sie haben mehrere Methoden.

Eine der einfachsten Methoden ist:

MYVAR=$(yourcommand)
echo $"MYVAR"

Zum Beispiel:

MYVAR=$(ls /)
echo $"MYVAR"
0
Bertrand SCHITS

Wir verwenden ein Konstrukt, das xargs und ctrl-d zum Brechen verwendet. Ich bin damit nicht ganz zufrieden, aber es macht sicherlich die Aufgabe, mehrzeilige Benutzereingaben zu übernehmen und diese in eine Variable zu stopfen (Formatierung intakt). (Die erste und dritte Zuweisung fügen Anführungszeichen um den Inhalt der xargs-Eingabe hinzu.)

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

Wir verwenden ErinnerungBody als Hauptteil einer E-Mail, die per Post (per Bash) gesendet wird.

0
JamesIsIn