Ich habe eine Steuerdatei – cntl.txt
2
3
5
Datendatei – data.txt
red
blue
yellow
green
violet
orange
Ich muss die passenden Zeilen aus der Steuerdatei lesen. Die erwartete Ausgabe lautet:
blue
yellow
violet
Antwort1
Beispiel einer sehr ineffizienten Lösung:
for i in $(<control.txt); do awk -v c=$i 'NR~c{ print $0 }' data.txt; done;
Ich berichte auch von einer guten Lösung, die ich heute Abend gelernt habe:
awk 'FNR==NR{ z[$0]++;next }; FNR in z' control.txt data.txt
Antwort2
Nur mitPOSIX spezifiziertFunktionen von Sed:
sed -n -e "$(sed '/./s/$/p/' cntl.txt)" data.txt
Wenn Ihre Datei außer Zahlen auch Zeilen enthält, kann natürlich cntl.txt
eine Fehlermeldung auftreten. Wenn die Datei jedoch leere Zeilen enthält, werden diese korrekt verarbeitet (d. h. sie wirken sich nicht auf die Ausgabe aus).
Antwort3
Versuche dies:
join <(nl data.txt|sort -k1b,1) <(cat cntl.txt|sort -k1b,1) | sort -nk1,1 | cut -d' ' -f2-
nl - zählt die Zeilen für Sie auf
1 red
2 blue
3 yellow
4 green
5 violet
6 orange
| sort -k1b,1 - sortiert sie lexikografisch nach der Zeilennummer (erstes Feld)
cat cntl.txt| sort -k1b,1 – sortiert die Steuerdatei in der gleichen Reihenfolge
2
3
5
join <() <() - verbindet die sortierten (und nummerierten) „Daten“ mit der sortierten „Steuerung“ im ersten Feld (also der Zeilennummer).
2 blue
3 yellow
5 violet
|sort -nk1,1 – sortiert die Ergebnisse numerisch neu (um die Zeilen wieder in die richtige Reihenfolge zu bringen)
| cut -d' ' -f2- - löscht das Zeilennummernfeld
blue
yellow
violet
Antwort4
Eine weitere mögliche Lösung:
IFS=$'\n' read -d '' -r -a colors < 'data.txt'; unset IFS;
for i in $(<cntl.txt); do
echo ${colors[i-1]}
done
Die IFS-Zeile richtet den internen Dateitrenner als Zeilenumbruch ein und fügt jede Zeile aus data.txt in das Array ein. Danach durchlaufen Sie die Zeilen in cntl.txt und drucken Array-Elemente mit dem angegebenen Index daraus (minus 1, da Sie data.txt bei 1 und nicht bei 0 beginnen, da dies sonst unnötig wäre).