Ich wollte wissen, ob es eine Möglichkeit gibt, aus zwei Eingabedateien in einer verschachtelten while-Schleife jeweils eine Zeile zu lesen. Nehmen wir zum Beispiel an, ich habe zwei Dateien FileA
und FileB
.
Datei A:
[jaypal:~/Temp] cat filea
this is File A line1
this is File A line2
this is File A line3
Datei B:
[jaypal:~/Temp] cat fileb
this is File B line1
this is File B line2
this is File B line3
Aktuelles Beispielskript:
[jaypal:~/Temp] cat read.sh
#!/bin/bash
while read lineA
do echo $lineA
while read lineB
do echo $lineB
done < fileb
done < filea
Ausführung:
[jaypal:~/Temp] ./read.sh
this is File A line1
this is File B line1
this is File B line2
this is File B line3
this is File A line2
this is File B line1
this is File B line2
this is File B line3
this is File A line3
this is File B line1
this is File B line2
this is File B line3
Problem und gewünschte Ausgabe:
Dadurch wird FileB für jede Zeile in FileA vollständig durchlaufen. Ich habe versucht, continue, break, exit zu verwenden, aber keines von ihnen ist für das Erreichen der gewünschten Ausgabe gedacht. Ich möchte, dass das Skript nur eine Zeile aus Datei A und dann eine Zeile aus Datei B liest, die Schleife verlässt und mit der zweiten Zeile von Datei A und der zweiten Zeile von Datei B fortfährt.
[jaypal:~/Temp] cat read1.sh
#!/bin/bash
count=1
while read lineA
do echo $lineA
lineB=`sed -n "$count"p fileb`
echo $lineB
count=`expr $count + 1`
done < filea
[jaypal:~/Temp] ./read1.sh
this is File A line1
this is File B line1
this is File A line2
this is File B line2
this is File A line3
this is File B line3
Ist das mit while-Schleife möglich?
bash
shell-script
io-redirection
Jaypal Singh
quelle
quelle
paste -d '\n' file1 file2
Antworten:
Wenn Sie sicher sind, dass ein Zeichen niemals in der ersten Datei vorkommt, können Sie Einfügen verwenden.
Beispiel für das Einfügen unter Verwendung der Standardbegrenzerregisterkarte:
Beispiel für eine Paste mit
@
:Beachten Sie, dass es ausreicht, wenn das Zeichen garantiert nicht in der ersten Datei vorkommt. Dies
read
wird ignoriert,IFS
wenn die letzte Variable gefüllt wird. Selbst wenn@
es in der zweiten Datei vorkommt, wird es nicht aufgeteilt.Beispiel für das Einfügen mit einigen Bash-Funktionen für wohl saubereren Code:
Verwendete Bash-Funktionen: ansi c string (
$'\t'
) und process substitution (<(...)
), um die while-Schleife in einem Subshell-Problem zu vermeiden .Wenn Sie nicht sicher sind, dass in beiden Dateien niemals ein Zeichen vorkommt, können Sie Dateideskriptoren verwenden .
Nicht viel getestet. Könnte in leeren Zeilen brechen.
Die Dateideskriptoren 0, 1 und 2 werden bereits für stdin, stdout und stderr verwendet. Dateideskriptoren ab 3 Jahren sind (in der Regel) kostenlos. Das Bash-Handbuch warnt davor, Dateideskriptoren zu verwenden, die größer als 9 sind, da sie "intern verwendet" werden.
Beachten Sie, dass offene Dateideskriptoren an Shell-Funktionen und externe Programme vererbt werden. Funktionen und Programme, die einen geöffneten Dateideskriptor erben, können aus dem Dateideskriptor lesen (und in ihn schreiben). Sie sollten darauf achten, alle nicht benötigten Dateideskriptoren zu schließen, bevor Sie eine Funktion oder ein externes Programm aufrufen.
Hier ist dasselbe Programm wie oben, wobei die eigentliche Arbeit (das Drucken) von der Metaarbeit getrennt ist (zeilenweise aus zwei parallelen Dateien lesen).
Jetzt tun wir so, als hätten wir keine Kontrolle über den Arbeitscode und dieser Code versucht, aus welchem Grund auch immer, aus Dateideskriptor 3 zu lesen.
Hier ist eine Beispielausgabe. Beachten Sie, dass die zweite Zeile aus der ersten Datei aus der Schleife "gestohlen" wird.
So schließen Sie die Dateideskriptoren, bevor Sie externen Code (oder einen anderen Code) aufrufen.
quelle
Öffnen Sie die beiden Dateien in unterschiedlichen Dateideskriptoren . Leiten Sie die Eingabe des
read
eingebauten in den Deskriptor um, mit dem die gewünschte Datei verbunden ist. In bash / ksh / zsh können Sieread -u 3
anstelle von schreibenread <&3
.Dieses Snippet stoppt, wenn die kürzeste Datei verarbeitet wurde. Siehe Lesen von zwei Dateien in eine IFS while-Schleife - Gibt es in diesem Fall eine Möglichkeit, ein Null-Diff-Ergebnis zu erhalten? Wenn Sie die Verarbeitung bis zum Ende beider Dateien fortsetzen möchten.
Siehe auch Wann würden Sie einen zusätzlichen Dateideskriptor verwenden? für zusätzliche Informationen zu Dateideskriptoren, und warum wird `while IFS = read` so oft verwendet, anstatt` IFS =; während gelesen..`? für eine Erklärung von
IFS= read -r
.quelle
Ich weiß, Sie möchten ein Shell-Skript, aber vielleicht möchten Sie sich den
paste
Befehl ansehen .quelle
paste
ist auch cool.Versuchen Sie den folgenden Befehl:
quelle
Alternativ können Sie die Datei auch in eine Array-Variable schlürfen, indem Sie jede Zeile der Datei mit dem Befehl mapfile von bash in das Array [line_of_file_index] einbinden. Ich bin mir jedoch nicht sicher, ob es nur für Bash3 höher oder Bash4 ist.
http://wiki.bash-hackers.org/commands/builtin/mapfile
quelle