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 == 1
wäre besser lesbar IMO.
Verwendung von split
(GNU Coreutils):
split -nr/1/4 input > output
-n
CHUNKS
Ausgabedateien generierenund CHUNKS
als
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 1
und 4
in $n
und $i
Variablen:
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
readlines
mö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 iter
Zeilen vom Anfang der Datei gezogen und dann nur die letzten ausgegeben werden. Es erhöht dann iter
durch skips
und wiederholt, solange der Wert iter
nicht überschritten hat das lines
in 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 lines
mit einer Zeile pro Eintrag liest . Die -t
Option entfernt die letzten Zeilenumbrüche.
Wenn Sie jede vierte Zeile ab Zeile 4 drucken möchten, können Sie dies in einem Befehl mithilfe mapfile
der Rückrufoption tun, bei -C
der 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 printf
eingebaute; Der Formatcode %.0s
unterdrü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, input
bevor 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 printf
vier Einträge des Arrays lines
gleichzeitig 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'