Wiederholen Sie jede Zeile mehrmals

17

Möchte, dass jede Zeile in einer Datei eine feste Anzahl von Malen wiederholt wird.

zB jede Zeile viermal wiederholen lassen:

a
b
c

wird:

a
a
a
a
b
b
b
b
c
c
c
c

Ich habe einige Suchen durchgeführt, und es gibt eine Menge Fragen und Antworten in umgekehrter Reihenfolge, z. B. das Zusammenführen doppelter Zeilen zu einzelnen Zeilen und vielleicht ein paar zum Verdoppeln von Zeilen durch erneutes Drucken.

Es wäre einfach, dies in C zu tun, aber ich wünschte, ich wüsste mehr über die nativen Befehle, damit ich nicht die ganze Zeit auf diese Art von einmaligen Auswürfen zurückgreifen müsste.

Yimin Rong
quelle

Antworten:

19
  • Perl:

    perl -ne 'for$i(0..3){print}' file

    und ich muss diesen Beitrag als Kommentar von @derobert hinzufügen, weil er einfach cool ist:

    perl -ne 'print "$_" x4'
  • awk und Varianten:

    awk '{for(i=0;i<4;i++)print}' file
  • bash

    while read line; do for i in {1..4}; do echo "$line"; done; done < file
terdon
quelle
1
awkEs sind forkeine geschweiften Klammern erforderlich, wenn nur ein Befehl wiederholt werden muss. Und perlist einfacher , wenn Sie verwenden foreachSchleife: for$i(0..3){print}.
Manatwork
4
Alternative Perl: perl -ne 'print(($_)x4)'. Außerdem sollten Sie $line(in Echo) in Ihrer Bash-Version zitieren .
Derobert
In meinem Fall brauchte ich Windows-Endungen. wie man hier sehen kann mitBEGIN { ORS="\r\n" }
The Red Pea
34

Ich frage mich, ob dies ein Golfspiel wird :

sed 'p;p;p' 
awk '1;1;1;1' 
perl -lpE 'say;say;say'   # if Paul McCartney and Michael Jackson were hackers...

Erläuterung:

Der pBefehl von sed besteht darin, die aktuelle Zeile auszudrucken. Standardmäßig wird die aktuelle Zeile gedruckt, bevor zur nächsten Zeile gewechselt wird (deshalb muss sed das Deaktivieren -nzulassen). Einige ältere Seds haben kein Semikolon (glaube ich), so dass es möglich ist, dass Sie dies tun müssensed -e p -e p -e p

Awk arbeitet mit condition {action}Paaren. Wenn die Aktion weggelassen wird, wird standardmäßig die aktuelle Zeile gedruckt, wenn die Bedingung true zurückgibt. Awk behandelt wie viele C-ähnliche Sprachen 1als wahr. (Der Vollständigkeit halber wird die Aktion für jeden Datensatz ausgeführt, wenn die Bedingung weggelassen wird.)

Viele Perl-Funktionen nutzen die "Standard" -Variable. Dieser Einzeiler entspricht (auf Perl 5.16):

$ perl -MO=Deparse -lpE 'say;say;say'
BEGIN { $/ = "\n"; $\ = "\n"; }
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    say $_;
    say $_;
    say $_;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
Glenn Jackman
quelle
1
+1, wenn 1ja, gewinnst du :) Was genau macht das in awk? Abkürzung für print $0?
Terdon
3
Awk-Anweisungen bestehen aus einer Bedingung und einem Block. Beide sind optional, einer muss jedoch vorhanden sein. Die Standardbedingung ist 1(true). Der Standardblock ist äquivalent zu {print}. Die Anweisung 1würde also bedeuten, den aktuellen Zeilenpuffer ( {print}) zu drucken . ( {print}und {print $0}sind meistens gleich, qed.)
Arcege
Ich habe noch nie von einem gehört sed, das keine Semikolons als Befehlsabschlusszeichen unterstützt. gibt es so etwas wirklich?
Wildcard
4
sed -n '{p;p;p;p;}' file

awk '{print;print;print;print;}' file
Hauke ​​Laging
quelle
4

Sie können dies tun , ohne sed, perloder awk.

$ for i in `cat <file>` ; do seq <#> <#> | xargs -i -- echo $i ; done

oder mit einer while-Schleife:

$ while read i ; do seq <#> <#> | xargs -i -- echo $i ; done < <file>

Beispiele

for-Schleife
$ for i in `cat sample.txt` ; do seq 1 3 | xargs -i -- echo $i ; done
a
a
a
b
b
b
c
c
c
while-Schleife
$ while read i; do seq 1 2| xargs -i -- echo $i;done < sample.txt
a
a
b
b
c
c
slm
quelle
Ich denke, dass die for-Schleifenversion in allen Zeilen mit Leerzeichen unterbrochen wird, daher sollte die while-Schleife bevorzugt werden. Ansonsten +1 da ich ein Trottel für Shell-Lösungen bin.
Übelsuppe
@evilsoup - ja, jemand anderes hat dies auch in einem Code erwähnt, den ich in einem anderen Q & A gepostet habe. Ich denke, das ist der Hauptvorteil von while over for. Die while-Schleife ist tolerant gegenüber dem $ IFS-Trennzeichen und wird am Zeilenende geteilt, wohingegen die for-Aufteilung bei $ IFS erfolgt.
slm
1

Mit rein shell:

repeats=4
while read line; do yes $line|head --lines=$repeats; done < infile > outfile
user176581
quelle
Weiß jemand, wie man Ja --helpals Zeichenfolge anstelle einer Option betrachtet? [Betrachten Sie den Fall, wo lineist --helpoder eine andere Option]
user176581
yes,yes -- --help
don_crissti
Mit yesund headbedeutet, dies ist nicht "rein Shell"
Glenn Jackman
1

Dies könnte für Sie funktionieren (GNU sed):

sed 'h;:a;s/[^\n]\+/&/4;t;G;ba' file

Wiederholt jede Zeile 4 Mal.

Oder wenn Sie es vorziehen:

sed 'h;:a;s/\n/&/3;t;G;ba' file

Wo Sie jede Zeile noch 3 Mal wiederholen.

Potong
quelle
1

@potongs Antwort funktioniert nicht mit Leerzeilen, das Ersetzen \+durch *sollte das Problem beheben:

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
Jan Kos
quelle