Entfernen Sie das Zeilenumbruchzeichen nur alle N Zeilen


16

Bei der Verarbeitung von Text muss das Zeilenumbruchzeichen alle zwei Zeilen entfernt werden.

Beispieltext:

this is line one
and this is line two
the third and the
fourth must be pasted too

Gewünschte Ausgabe:

this is line one and this is line two
the third and the fourth must be pasted too

Ich habe eine whileSchleife ausprobiert , aber eine while-Schleife ist eine schlechte Übung. Ist es möglich, es mit troder einem anderen Befehl zu tun ?


4
Der Titel sagt "alle N Zeilen", aber in der Frage und im Beispiel ist es "alle 2 Zeilen". Die meisten Antworten funktionieren nur für N = 2. Suchen Sie etwas, das für alle N funktioniert?
JigglyNaga

Das ist der Schlüssel. Alle antworteten für 2 Zeilen, aber ich müsste N = 3 oder N = 4 verwenden
jomaweb

Antworten:


24

paste(auch ein einfaches POSIX-Standardprogramm wie tr) ist Ihr Werkzeug dafür.

Vorausgesetzt , dass Sie diese Zeilenumbrüche durch ein Leerzeichen ersetzt wollen , anstatt nur entfernt wie in Ihrem Beispiel:

paste -d ' ' - - < file

Oder:

paste -sd ' \n' file

Ersetzen Sie ' 'durch, '\0'wenn Sie tatsächlich möchten, dass sie entfernt werden.

2 von 3 ersetzen:

paste -sd '  \n' file

1 von 3, beginnend mit der Sekunde:

paste -sd '\n \n' file

Und so weiter.

Ein weiterer Vorteil pasteist, dass keine nicht terminierte Leitung übrig bleibt. Wenn Sie beispielsweise jede neue Zeile in einer Datei entfernen (wie mit tr -d '\n' < fileoder tr '\n' ' ' < file), wird überhaupt keine Zeile angezeigt, da Zeilen mit einem neuen Zeilenumbruch abgeschlossen werden müssen. Daher ist es im Allgemeinen besser, pastestattdessen (wie in paste -sd '\0' fileoder paste -sd ' ' file) das nachfolgende Zeilenumbruchzeichen hinzuzufügen, das für einen gültigen Text erforderlich ist.


11

Mit modernem GNU sed

sed -rz 's/\n([^\n]*\n)/ \1/g' sample.text

Und awk

awk '{getline line2;print $0, line2}' sample.text

3
Dieser sedAnsatz bedeutet, die gesamte Datei im Speicher zu verschlucken (vorausgesetzt, sie enthält keine NUL-Bytes) und teure reguläre Ausdrücke zu ersetzen. Ich kann den Vorteil gegenüber dem Standardansatz nicht erkennen sed 'N;s/\n/ /'.
Stéphane Chazelas

6

Verwenden Sie seddazu wie unten gezeigt:

SHW@SHW:/tmp $ cat a
this is line one
and this is line two
the third and the
fourth must be pasted too

SHW@SHW:/tmp $ sed 'N;s/\n/ /' a -i

SHW@SHW:/tmp $ cat a
this is line one and this is line two
the third and the fourth must be pasted too

4

Ein anderer Weg ist xargs:

$ < txt xargs -d '\n' -n 2 echo
this is line one and this is line two
the third and the fourth must be pasted too

wo

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

Diese Lösung ist jedoch zu umfangreich, da echofür jede Zeile ein Prozess ausgeführt wird. Daher sollte neben Spielzeugbeispielen eine Lösung auf der Basis von awk / sed oder ähnlichem bevorzugt werden.


1
Abhängig von Ihrer echoImplementierung haben Sie auch Probleme mit Backslash-Zeichen oder einigen Zeilen, die mit -(like --helpoder -nenemit GNU echo) beginnen. Beachten Sie auch, dass dies -deine GNU-Erweiterung ist.
Stéphane Chazelas

Um Probleme mit zu vermeiden echo, können Sie dies verwenden:< txt xargs -d '\n' -n 2 printf -- '%s %s\n'
nyuszika7h

4

Das ist eigentlich extrem einfach in vim. Verwenden Sie den JBefehl, um jede Zeile zusammenzufügen , und %normwenden Sie ihn dann gleichzeitig auf jede Zeile an. Beispielsweise

:%norm J<CR>

(Nur für den Fall, dass Sie nicht mit vim vertraut sind, <CR>bedeutet nur eintreten)

Dies funktioniert sogar, um eine beliebige Anzahl von Zeilen zu verbinden. Zum Beispiel, um alle zehn Zeilen zu verbinden wäre

:%norm 9J<CR>

Wenn Sie mit vim nicht vertraut sind und es lieber als Befehlszeilentool als als interaktiven Texteditor verwenden möchten, können Sie Folgendes tun:

vim myfile -c '%norm J' -c 'wq'

Würde der Downvoter gerne erklären, was ich tun kann, um diese Antwort zu verbessern?
DJMcMayhem

3
$ awk '{printf "%s%s",$0,(NR%2?" ":"\n")}' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

Dabei wird jede Zeile gedruckt $0, gefolgt von einem Leerzeichen oder einer neuen Zeile, je nachdem, ob die Zeilennummer NRgerade oder ungerade ist.

Der Ausdruck NR%2?" ":"\n"ist eine ternäre Aussage. Der Ausdruck wird NR%2mit true (ungleich null) ausgewertet, wenn die Zeilennummer ungerade ist. In diesem Fall gibt der ternäre Ausdruck ein Leerzeichen zurück. Wenn der Wert false (Null) ergibt, wird die neue Zeile zurückgegeben.

Alternative

Wie von Costas in den Kommentaren vorgeschlagen:

$ awk '{ORS=(NR%2?" ":RS)}1' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

Hier wird die ternäre Anweisung NR%2?" ":RSverwendet, um entweder ein Leerzeichen oder das Trennzeichen für den Eingabesatz zurückzugeben ( RSStandard = Newline). Dieser Wert wird dem Ausgabesatztrennzeichen zugewiesen ORS. Am 1Ende des Befehls steht die kryptische Abkürzung von awk für print-the-record.


Sie können noch 3 Zeichen speichern: die ()Klammern und das Leerzeichen danach printf;)
maxschlepzig

1
Ternär? Oh! 'NR%2{printf("%s ",$0);next}1'
Costas

Mit maxschlepzigs Antwort und ternärer Aussage:'{ORS=(NR%2?" ":RS)}1'
Costas

@Costas Das gefällt mir. Antwort mit ORSLösung aktualisiert .
John1024

2

Generische Lösung, durch die 5Anzahl der erforderlichen Zeilen ersetzen

$ # eof to ensure last line has newline ending
$ seq 16 | perl -pe 's/\n/ / if ++$i%5 && !eof'
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

$ # or just use pr
$ seq 16 | pr -5ats' '
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

1

Sie können dafür verwenden awk:

$ awk '{c="\n"} NR%2 {c=" "} { printf("%s%s", $0, c) } ' txt

Es produziert:

this is line one and this is line two
the third and the fourth must be pasted too

wo:

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

Die awkAktionen werden für jede Zeile ausgeführt, die spezielle Variable $0referenziert die aktuelle Zeile, NRist die aktuelle Zeilennummer (beginnend bei 1). Die zweite Aktion wird durch den Ausdruck geschützt NR%2, der die Modulo-Operation ist. Somit c=" "wird nur ausgeführt, wennNR%2 wahr ist, dh für ungeradee Zeilennummern.

Die awkSyntax ist C-ähnlich, aber einige Elemente sind in bestimmten Kontexten optional - z. B. Semikolons.


Ihre cVariable ist ORS:'NR%2{ORS=" "}1;{ORS=RS}'
Costas

0

Verwenden von ed:

$ cat text
this is line one
and this is line two
the third and the
fourth must be pasted too
this is line one
and this is line two
the third and the
fourth must be pasted too

$ ed text <<'END_ED'
g/./s/$/ /\
j
w text.new
END_ED
164
164

$ cat text.new
this is line one and this is line two
the third and the fourth must be pasted too
this is line one and this is line two
the third and the fourth must be pasted too

Die edBearbeitungsbefehle gfügen für jede Zeile ( wenden eine Reihe von Bearbeitungsbefehlen auf jede Zeile an, die dem angegebenen regulären Ausdruck entspricht) ein Leerzeichen am Ende hinzu und verbinden es mit der nächsten Zeile. Dann schreibt es den resultierenden Text in eine Datei namens text.new.


0

Mit Rubin.

Ich gehe davon aus, dass jeder Zeilenblock nverbunden werden soll. Angenommen n = 3, die Eingabedatei lautet 'infile'und die Ergebnisse sollen in die Datei geschrieben werden 'outfile'.

Konstruiere eine Datei

Ruby -e "File.write 'infile', <<_
> Line 1
> Line 2
> Line 3
> Line 4
> Line 5
> Line 6
> Line 7
> _"

Bestätigen Sie den Inhalt der Datei

ruby -e "p File.read 'infile'"
  # "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\n"

Zeilenumbrüche entfernen und in Datei schreiben

ruby -e "File.write 'outfile', File.readlines('infile').
  each_with_index { |line,i| line.chomp! unless (i+1)%3==0 }"

Bestätigen Sie den Inhalt

ruby -e "puts File.read 'outfile'"
  # ["Line 1", "Line 2", "Line 3\n", "Line 4", "Line 5", "Line 6\n", "Line 7"]

1
Gut Theoretisch rubyist U & L off-topic. Da Sie es jedoch über die Befehlszeile mit verwenden ruby -e, ist es themenbezogen genug.
voraussichtlich
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.