Eingang:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Erwartete Ausgabe:
1
2
3
4
Ich muss also nur den 1., 5., 9., 13. Wert der Datei in der Ausgabedatei haben. Wie macht man das?
Eingang:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Erwartete Ausgabe:
1
2
3
4
Ich muss also nur den 1., 5., 9., 13. Wert der Datei in der Ausgabedatei haben. Wie macht man das?
Antworten:
Verwenden von AWK:
awk '!((NR - 1) % 4)' input > output
Herauszufinden, wie dies funktioniert, bleibt dem Leser als Übung überlassen.
NR % 4 == 1wäre besser lesbar IMO.
Verwendung von split (GNU Coreutils):
split -nr/1/4 input > output
-nCHUNKSAusgabedateien generierenund CHUNKSals
r/K/N Verwenden Sie die Round-Robin-Verteilung und geben Sie nur Kth von N an stdout aus, ohne Zeilen / Datensätze zu teilenMit GNU sed:
sed '1~4!d' < input > output
Mit Standard sed:
sed -n 'p;n;n;n' < input > output
Mit 1und 4in $nund $iVariablen:
sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'
Python-Version, nur zum Spaß:
with open('input.txt') as f:
for i, line in enumerate(f.readlines()):
if i%4 == 0:
print(line.strip())
enumerate(f)sollte in der Lage sein, die Arbeit zu erledigen, während weniger Speicher verbraucht wird
readlinesmöchten (wodurch die gesamte Datei in den Speicher geschlürft wird), können f.readlines()[::4]Sie jede vierte Zeile abrufen. So können Sie verwenden print(''.join(f.readlines()[::4])).
POSIX sed: Diese Methode verwendet das posixly sed und kann daher überall ausgeführt werden, oder zumindest die Samen, die posix respektieren.
$ sed -ne '
/\n/!{
H;s/.*//;x
}
:loop
$bdone
N;s/\n/&/4
tdone
bloop
:done
s/.//;P
' input.file
Eine andere ist eine programmatische Sed-Code-Generierung für Skalierbarkeitszwecke:
$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file
Perl: Wir füllen Array A auf, bis es 4 groß ist. Dann drucken wir das erste Element und löschen das Array.
$ perl -pe '
$A[@A] = @A ? <> : $_ while @A < 4;
$_ = (splice @A)[0];
' input.file
Call with scriptname filename skip(4 in Ihrem Fall) Es funktioniert, indem iterZeilen vom Anfang der Datei gezogen und dann nur die letzten ausgegeben werden. Es erhöht dann iterdurch skipsund wiederholt, solange der Wert iternicht überschritten hat das linesin file.
#!/bin/bash
file="$1"
lines=`wc -l < "$file"`
skips="$2" || "4"
iter=1
while [ "$iter" -le "$lines" ]; do
head "$file" -n $iter | tail -n 1
iter=$(( $iter + $skips ))
done
Pure Bash:
mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done
mapfile ist eine in Bash 4 hinzugefügte integrierte Datei, die Standardeingaben in ein hier genanntes Array linesmit einer Zeile pro Eintrag liest . Die -tOption entfernt die letzten Zeilenumbrüche.
Wenn Sie jede vierte Zeile ab Zeile 4 drucken möchten, können Sie dies in einem Befehl mithilfe mapfileder Rückrufoption tun, bei -Cder der bereitgestellte Code alle paar Zeilen mit dem angegebenen Intervall ausgeführt wird -c. Der aktuelle Array-Index und die nächste zuzuweisende Zeile werden dem Code als Argumente übergeben.
mapfile -t -c4 -C 'printf "%.0s%s\n"' < input
Dies verwendet das printfeingebaute; Der Formatcode %.0sunterdrückt das erste Argument (den Index), sodass nur die Zeile gedruckt wird.
Sie könnten den gleichen Befehl verwenden, um jede vierte Zeile ab Zeile 1, 2 oder 3 zu drucken, aber Sie müssten 3, 2 oder 1 Zeilen voranstellen, inputbevor Sie sie eingeben mapfile, was meiner Meinung nach mehr Probleme als wert ist .
Dies funktioniert auch:
mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"
Hier werden printfvier Einträge des Arrays linesgleichzeitig verbraucht , wobei nur der erste gedruckt und die anderen drei mit übersprungen werden %.0s. Ich mag das nicht, da Sie für verschiedene Intervalle oder Startpunkte manuell mit der Formatzeichenfolge herumspielen müssen.
sed -n '1~4p'