Wie kann ich die Endzeile durch festen Text ersetzen, wenn die nächste Zeile mit einer definierten Menge von Zeichen beginnt?

892
Juhele

Ich habe mehrere große Dateien mit einigen Maßen.

Es sieht so aus:

N 12344;PE 9.9999999;... #S 0 0 31 44 75 130 165 196... #S_+ "2 5 2 3 3 1 1 2 3 1 2 2...  N 12345;PE 9.9999999;... #S 0 0 34 57 84 133 152... #S_+ "1 0 1 1 2 3 0 0 0...  N 12346;PE 9.9999999;... #S 0 0 31 44 73 140 169... #S_+ "3 3 4 0 0 2 1 2 4...  N 25104;PE 9.9999999;... #S 0 0 36 52 102 108 145... #S_+ "1 1 0 1 0 0 3 0 1...  N 25105;PE 9.9999999;... #S 0 0 32 58 88 130 143... 

Beispiel ist hier: http://pasted.co/d9806b7c4

Die Datei ist viel größer, aber ich habe einen Teil der Daten durch "..." ersetzt, um sie zu verkürzen.

Ich muss die Zeilenende vor "#S" irgendwie ersetzen - in der Tat fügen Sie einfach die "N" -Zeile mit den folgenden beiden Zeilen in einer Zeile zusammen (oder mit den folgenden drei Zeilen, damit ich die Leerzeilen entfernen kann). Erwarten Sie eine Ausgabe wie folgt:

N 12344;PE 9.9999999; #S 0 0 31 44 75 130 165 196 #S_+ "2 5 2 3 3 1 1 2 3 1 2 2... N 12345;PE 9.9999999; #S 0 0 34 57 84 133 152 #S_+ "1 0 1 1 2 3 0 0 0... N 12346;PE 9.9999999; #S 0 0 31 44 73 140 169 #S_+ "3 3 4 0 0 2 1 2 4... N 25104;PE 9.9999999; #S 0 0 36 52 102 108 145 #S_+ "1 1 0 1 0 0 3 0 1... N 25105;PE 9.9999999; #S 0 0 32 58 88 130 143... 

Ist es möglich, ein Befehlszeilendienstprogramm in Linux zu verwenden?

Mein Wissen ist in diesem Bereich ziemlich begrenzt, ich würde mich über jede Hilfe freuen.

Vielen Dank

2
danke an grawity für die hilfe beim code :-) Juhele vor 5 Jahren 0
@Pimp Juice IT: OK, ich habe die Frage aktualisiert. Juhele vor 5 Jahren 1
Hi @Juhele kannst du das Ausgabeformat besser spezifizieren: Müssen Sie die erste Zeile z. B. "PE 9.9999999;" abschneiden, müssen Sie die zweite nach der 7. (8.) Zahl schneiden oder beim Schreiben _merge das " N "Zeile mit den folgenden zwei Einsen_? Was ist mit dem "", das nur in der Ausgabe vorhanden ist? Ich gebe etwas zu Ihrem Beitrag, bitte überprüfen Sie es. Es kann eine unvollständige Datei sein. BTW für den einfachsten Fall, in dem Sie bereits mehr als eine gute Antwort haben. Hastur vor 5 Jahren 0

6 Antworten auf die Frage

4
xenoid

Mit sed:

sed -z -e 's/\n#S/ #S/g' -e 's/\nN /N /g' data 

In Zeitlupe:

  • -z lässt sed die Datei als einzelne Zeile betrachten (die Zeilenenden sind also reine Zeichen)
  • 's/\n#S/#S/g'ersetzt alle kurz vor einem LF auftretenden LF #Sdurch ein Leerzeichen
  • -e 's/\nN /N /g'ersetzt alle LFs vor N(dh die Leerzeilen)
4
xenoid

Mit paste(dies erfordert immer Gruppen von 4 Zeilen):

 paste -s -d ' \n' data 

In slo-mo:

  • paste -s verkettet die Zeilen aus der Datei
  • -dgibt die Zeichen an, die als Trennzeichen eingefügt werden sollen. Wenn mehrere Zeichen vorhanden sind, werden sie in einem Round-Robin-Verfahren verwendet, also mit 3 Leerzeichen und einem LF:
    • das erste Leerzeichen wird beim ersten Spleiß ( Nbis #S) verwendet,
    • der zweite Raum wird auf dem zweiten Splice ( #Sto #S) verwendet,
    • der dritte Platz wird auf dem dritten Spleiß verwendet ( #Szu Leerzeile),
    • das letzte Trennzeichen, ein LF, wird für den vierten Spleiß verwendet (leere Zeile bis N)
    • und der Zyklus wiederholt sich für die nächsten 4 Zeilen.
4
Kamil Maciorowski

Dies ist eine tragbare Lösung mit POSIXsed, die die folgenden Regeln implementiert:

  • Leerzeilen werden gestrichen.
  • Jede Zeile, die mit beginnt, #Swird mit der vorherigen nicht leeren Zeile mit einem einzigen Leerzeichen zwischen ihnen zusammengefügt, es sei denn, es gibt keine vorherige nicht leere Zeile.

Der Code:

<data sed '/^$/ d; :start; N; s/\n$//; t start; s/\n#S/ #S/; t start; P; D' 

Dasselbe mit Kommentaren (noch funktionierender Code):

<data sed ' /^$/ d # If empty line read, delete it and start a new cycle. :start # A label. N # Read additional line, there are now two lines in the pattern space. s/\n$// # If the second line is empty, replace the newline with nothing. t start # If the above replacement occurred, go to start (to add another line). # Otherwise s/\n#S/ #S/ # if the second line starts with #S, replace the newline with space. t start # If the above replacement occurred, go to start (to add another line). # Otherwise # (i.e when non-empty line not starting with #S occurred) P # print the pattern space up to the first newline and... D # delete the initial segment of the pattern space # through the first newline (i.e. everything just printed), # and start the next cycle with the resultant pattern space # and without reading any new input # (in our case the new input will be explicitly read by N then). ' 

Beachten Sie, dass die Lösung sedMusterbereich verwendet, um viele Eingabezeilen zu akkumulieren. Diese Bemerkung gilt:

Die Muster- und Haltebereiche müssen jeweils mindestens 8192 Bytes enthalten können.

Unmittelbar vor dem PBefehl enthält der Musterbereich eine (relativ lange) Zeile, die gedruckt werden soll, und eine einzige (relativ kurze) Eingabezeile sowie eine neue Zeile dazwischen. Natürlich hängt es von Ihren Daten ab, ob diese Struktur irgendwann 8192 Bytes überschreitet oder nicht. In diesem Fall schlagen einige sedImplementierungen möglicherweise fehl.

3
Toto

Perl verwenden:

perl -0 -ape 's/\R(?=\RN|#)/ /g' file.txt N 12344;PE 9.9999999;... #S 0 0 31 44 75 130 165 196... #S_+ "2 5 2 3 3 1 1 2 3 1 2 2... N 12345;PE 9.9999999;... #S 0 0 34 57 84 133 152... #S_+ "1 0 1 1 2 3 0 0 0... N 12346;PE 9.9999999;... #S 0 0 31 44 73 140 169... #S_+ "3 3 4 0 0 2 1 2 4... N 25104;PE 9.9999999;... #S 0 0 36 52 102 108 145... #S_+ "1 1 0 1 0 0 3 0 1... N 25105;PE 9.9999999;... #S 0 0 32 58 88 130 143... 

Regex erklären:

s/ : substitute \R : any kind of line break (ie. \r, \n, \r\n) (?= : positive lookahead, zero-length assertion that make sure we have after \RN : a line break followed by letter N | : OR # : # character ) : end lookahead / /g : replace with a space, global 
3
Hastur

awk ( gawk [ 1 ] )

Wie üblich anders als seddu verwenden kannst awk(und auf viele verschiedene Arten ...)

awk 'ORS=" "; NR % 4 == 0 && ORS="\n" ' data 

woher

  • ORS=" " behebt das Trennzeichen des Ausgabedatensatzes (standardmäßig eine Newline) in ein Leerzeichen (Sie können ändern)
  • NR % 4 == 0 && ORS="\n" In jeder 4. Zeile wird der Zeilenumbruch festgelegt \n
  • Wenn nichts anderes angegeben ist awk, wird die gesamte Zeile gedruckt
  • data ist Ihre Datendatei.

Wenn Sie möchten, können Sie Regex wie sed(in ähnlicher Weise) verwenden.


Eine Format-Check- Version mit awk

Auch wenn Sie nicht angefordert werden, möchten Sie möglicherweise eine abgeschnittene Datei verwalten, indem Sie die beschädigte Ausgabezeile löschen und einen Fehler und eine Fehlermeldung generieren .

awk '  else { print "Ohi " > "/dev/stderr" ; exit 65; } }' data 

woher

  • a=$0; fügt die vollständige Zeile in die Variable ein a
  • getline b; liest eine Zeile und setzt die Variable b
  • getline c; undurchschaubaren unergründlichen Befehl :-)
  • if (getline) Wenn es eine Zeile lesen kann ...
  • .............. druckt die 4 Zeilen
  • else druckt einen Fehler auf dem stderr-Gerät (Bildschirm oder anderes), das Sie hier anpassen können ...
  • exit 65 Rückgabe eines von 0 verschiedenen Exit-Codes --->error

Bonus: warum 65?

Bei der Suche nach einem guten Wert für Ihren Exit-Code [ 2 ] können Sie feststellen, dass /usr/include/sysexits.heinige C-Standards angezeigt werden sollten.

 #define EX_DATAERR 65 /* data format error */ 

65 ist am besten geeignet für einen Datenformatfehler ...

Als Antwort habe ich ehrlich gesagt 42 vorgezogen,
aber jeder von Null verschiedene Wert (und nicht reserviert [ 2 ] ) könnte gut sein und 65 ist der spezifische Wert.

Ein Nachteil ist jedoch: Das letzte Zeilenpaket kann aus drei bestehen (dh am Ende keine leere Zeile). oder auch nicht. Bei drei ist das letzte Zeichen Ihrer Ausgabe ein Leerzeichen und kein Zeilenumbruch. POSIX [definiert "Linie"] (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206) als `eine Folge von null oder mehr Zeichen plus eine Beendigung Zeichen ". Dies wird wahrscheinlich [nach hinten losgehen, wenn die Ausgabe weiter analysiert wird] (https://stackoverflow.com/a/7741505). Kamil Maciorowski vor 5 Jahren 0
Schön, aber das OP gibt unter anderem an, dass es sich nicht um ganz bestimmte Punkte handelt, die aus 4 Zeilen bestehen, zuletzt _blank_. Bei einer abgeschnittenen Datei kann die nächste unbekannte Verarbeitung jedoch beeinträchtigt werden. Eine nicht angeforderte Überprüfung der Formate ist außerhalb dieses Thread-Bereichs, und IMHO ist es eine gute Methode, __ einen Fehler zu generieren. Wenn Sie _solidity_ benötigen, sollten Sie sich lieber für ein Skript entscheiden (`awk`,` sed`, `perl` sind Skriptsprachen), mit dem Sie auch die Datenverarbeitung reproduzieren können. Dann muss man sich entscheiden, wie man mit Fehlern umgehen soll, aber das ist eine andere Frage ... `:-)` Ich versuche es einfach zu halten. Hastur vor 5 Jahren 0
@ KamilMaciorowski ... trotzdem habe ich noch eine Version mit Fehlerprüfung hinzugefügt ... Hastur vor 5 Jahren 0
0
KaRolthas

Sie können dies mit jedem Texteditor tun, der reguläre Ausdrücke wie Notepad ++ unterstützt.

Die neue Zeile besteht aus einem einfachen, nicht druckbaren Zeichen oder zwei Zeichen. In Windows normalerweise CarrigeReturn und LineFeed und in Unix-basierten Systemen normalerweise nur LineFeed.

Um sie anzuzeigen, müssen Sie ein nicht druckbares Zeichen anzeigen lassen (normalerweise ein Absatzsymbol). Siehe hier: https://imgur.com/cqiTvrp

Jetzt müssen Sie den regulären Ausdrucksersatz (STRG + H) verwenden, um CRLF # S bis #S zu ersetzen. Das Symbol für CR ist \ r und für LF ist \ n. Sie werden also mit \ r \ n # S oder \ n # S bis #S enden. https://imgur.com/GoeVn70

Oder Sie können es bei Bedarf durch SPACE ersetzen.

Die Frage lautet "Linux" .... xenoid vor 5 Jahren 0
Ich denke, reguläre Ausdrücke in Geany sind die gleichen. Wird als Beispiel Notepad ++ verwendet, da ich gerade bei Windows bin. KaRolthas vor 5 Jahren 0
Die Frage stellt auch ein Befehlszeilenprogramm ... xenoid vor 5 Jahren 0
Schön, funktioniert. Ich muss jetzt zumindest einige Dateien verarbeiten, so dass auch Notepad ++ hilfreich ist, wenn ich mit Windows auf meinem anderen Computer arbeite. Vielen Dank Juhele vor 5 Jahren 0