Ist das getestet? Normalerweise würde ein
nur in jeder Zeile, die mit einem großem "M" beginnt, dieses erste Zeichen löschen.
Das "Zusammenziehen" von Zeilen mittels "sed" funktioniert etwas anders, eine Möglichkeit wäre z.B. diese:
Code:
echo -n -e "1\n2\n3\n4\n\t5\n6\n" | sed -e ':x;$!N;s/[\n\t]//;tx'
Das sieht auf den ersten Blick etwas wild aus, ist aber aufgeschlüsselt auch wieder recht einfach. Man sollte dazu aber die (bzw. eine) "sed"-Dokumentation zumindest mal "angelesen" haben:
https://www.gnu.org/software/sed/manual/sed.txt
Man muß eigentlich nur wissen, daß "sed" ansonsten "stream-orientiert" arbeitet und die angegebenen Kommandos (die können auf der Kommandozeile angegeben werden - meist nach der Option "-e" - oder auch in einer gesonderten Datei stehen, mehrere aufeinanderfolgende Kommandos werden durch Semikolon getrennt bzw. in einer Kommandodatei durch eigene Zeilen) der Reihe nach auf jede einzelne Zeile der Eingabedatei angewendet werden ... daher findet eben so ein "Suchausdruck" keine passenden Daten, wenn sie sich über mehr als eine einzelne Zeile erstrecken.
Ist die "Kommandofolge" für eine einzelne Zeile abgearbeitet, wird die nächste Zeile der Eingabedatei gelesen und das Spiel beginnt von vorne. Als Besonderheit gibt es aber auch in so einer Kommandofolge die Möglichkeit, zu einer vorher festgelegten Marke zu springen, damit werden die Befehle in einer Schleife ausgeführt und solange es nicht bis zum Ende der Kommandofolge geht, wird auch nicht die nächste Zeile der Datei gelesen (jedenfalls nicht auf "normalem Weg").
Genau so funktioniert dieser Weg des "join lines":
Code:
:x - definiert so ein "label" (mit dem Wert "x", das eigentliche Kommando ist der Doppelpunkt), zu dem man springen kann
$ - bezeichnet beim "sed" die letzte Zeile der Eingabedatei, solange es als "Adresse" verwendet wird
! - negiert eine Adresse, die sich vor diesem Zeichen befindet ... "$!" steht also für "alle Zeilen der Eingabedatei, außer der letzten"
N - dieses Kommando fügt an die aktuelle Zeile einen Zeilenumbruch an und liest dann die nächste Zeile aus der Datei direkt hinter diesen "virtuellen Zeilenumbruch" in den sogenannten "pattern space" (das ist der "Arbeitsbereich", auf den sich die Kommandos beziehen)
Wenn wir jetzt erst einmal das Label "x" außer acht lassen, haben wir also ein Kommando, das bei allen Zeilen - außer bei der letzten in der Datei - die jeweils nächste Zeile mit einem dazwischenliegenden "newline" in den "pattern space" liest, was dann natürlich automatisch dazu führt, daß die gesamte Kommandofolge nur noch auf die Hälfte der "Durchläufe" kommt, weil ja immer zwei Zeilen zu einer einzelnen zusammengezogen werden im "pattern space".
Modifiziert man die Kommandofolge etwas, sieht man das ganz gut:
Code:
# echo -n -e "1\n2\n3\n4\n\t5\n6\n" | sed -e '$!N;s/\n/{NeueZeile}/'
1{NeueZeile}2
3{NeueZeile}4
5{NeueZeile}6
Solange man natürlich das "newline"-Zeichen, welches vom "N"-Kommando an die aktuelle Zeile angefügt wird, in seiner "ursprünglichen Form" bestehen läßt, sieht man in der Ausgabe den Effekt des "N"-Kommandos nicht, weil ja einfach wieder die Zeilen getrennt angezeigt würden.
Ersetzen wir das aber durch die Zeichenkette "{NeueZeile}", sieht man auch ganz gut, daß tatsächlich jetzt aus den 6 Zeilen der Eingabe nur noch 3 Zeilen in der Ausgabe werden, weil jeweils zwei Zeilen zu einer einzelnen zusammengefaßt wurden.
Das "N"-Kommando dürfen wir dabei nicht auf die letzte Zeile der Datei anwenden, weil die Dokumentation für dieses Kommando besagt:
man sed schrieb:
`N' - Add a newline to the pattern space, then append the next line of input to the pattern space. If there is no more input then `sed' exits without processing any more commands.
Auch das können wir leicht überprüfen, indem wir einfach mal 7 Zeilen Eingabe verarbeiten (bei gerader Anzahl von Zeilen spielt das keine Rolle, weil das "N" ja nur auf die vorletzte Zeile angewendet würde) und das "N"-Kommando auch auf diese letzte Zeile loslassen:
Code:
# echo -n -e "1\n2\n3\n4\n\t5\n6\n7" | sed -e 'N;s/\n/{NeueZeile}/;a====='
1{NeueZeile}2
=====
3{NeueZeile}4
=====
5{NeueZeile}6
=====
7
Das "a"-Kommando zum Hinzufügen der "====="-Folge als letzte Aktion, bevor zur nächsten Eingabezeile weiter gegangen wird, kommt nach der letzten Zeile also nicht mehr zur Ausführung, weil das "N"-Kommando mangels weiterer Zeilen in der Eingabedatei die Kommandofolge direkt abbricht ... im Gegenteil zu diesem Aufruf:
Code:
# echo -n -e "1\n2\n3\n4\n\t5\n6\n7" | sed -e '$!N;s/\n/{NeueZeile}/;a====='
1{NeueZeile}2
=====
3{NeueZeile}4
=====
5{NeueZeile}6
=====
7
=====
Hier wird also das "N"-Kommando für die letzte Zeile der Datei gar nicht erst ausgeführt (wegen "$!") und damit kommt das "a"-Kommando noch zum Zuge (das "s"-Kommando dazwischen findet halt nichts zum Ersetzen und bleibt wirkungslos). Das war zwar nur ein kleiner (hier eigentlich sogar nebensächlicher) Ausflug in die Verwendung von "N", aber es ist einer der beliebtesten Fehler, wenn man das "N"-Kommando in anderem Zusammenhang verwendet.
Zurück zum ursprünglichen Kommando ... die Abarbeitung für die erste Zeile ergibt also nach ":x;$!N" folgenden Inhalt des "pattern space":
Code:
1[COLOR="#FF0000"]\n[/COLOR]2
Jetzt wird mittels "s/\n//" das eingesetzte "newline"-Zeichen entfernt und damit ergibt sich folgender Inhalt des "pattern space":
Wäre hier jetzt die Kommandofolge beendet, würde die nächste Zeile aus der Eingabe gelesen (das wäre die mit der "3") und es ergäbe sich das oben gezeigte Bild der jeweils "paarig" zusammengezogenen Zeilen. Aber in der gezeigten Kommandofolge steht jetzt eben ein "t"-Kommando und das bedeutet: "Springe zur nachfolgend angegebenen Marke, wenn seit dem letzten Lesen einer Zeile der Datei irgendeine Ersetzung stattgefunden hat." ... genau das ist aber hier der Fall, denn das "newline"-Zeichen wurde ja durch "nichts" ersetzt. Damit springt also die Abarbeitung der Kommandofolge wieder zur Marke "x" und die besagt: "Solange das nicht die letzte Zeile der Datei ist, ziehe sie mit der nächsten zusammen." - das wäre hier jetzt die dritte Zeile.
Das setzt sich jetzt bis zur letzten Zeile so fort und am Ende erhält man eben eine Datei, die nur aus einer einzelnen Zeile besteht.
Wenn man dieses Vorgehen "visualisieren" möchte, fügt man einfach noch ein "p"-Kommando (das gibt den aktuellen Inhalt des "pattern space" aus, wenn es an der Reihe ist) in die Abarbeitung mit ein:
Code:
# echo -n -e "1\n2\n3\n4\n\t5\n6\n7" | sed -e ':x;$!N;s/\n/{NeueZeile}/;[COLOR="#FF0000"]p[/COLOR];tx'
1{NeueZeile}2
1{NeueZeile}2{NeueZeile}3
1{NeueZeile}2{NeueZeile}3{NeueZeile}4
1{NeueZeile}2{NeueZeile}3{NeueZeile}4{NeueZeile} 5
1{NeueZeile}2{NeueZeile}3{NeueZeile}4{NeueZeile} 5{NeueZeile}6
1{NeueZeile}2{NeueZeile}3{NeueZeile}4{NeueZeile} 5{NeueZeile}6{NeueZeile}7
1{NeueZeile}2{NeueZeile}3{NeueZeile}4{NeueZeile} 5{NeueZeile}6{NeueZeile}7
1{NeueZeile}2{NeueZeile}3{NeueZeile}4{NeueZeile} 5{NeueZeile}6{NeueZeile}7
Da wir ja auch eventuell vorhandene Tabulatoren entfernen wollen, ist das ursprüngliche "s"-Kommando eben "s/[\n\t]//", was jedes "newline"- oder "tab"-Zeichen entfernt. Wenn man ganz sicher gehen wollte, müßte man wohl die Tabulatoren und event.
führende Leerzeichen in einem gesonderten Durchlauf entfernen (weil man eben nicht jedes beliebige Leerzeichen ersetzen will), was dann in etwa so aussehen würde:
Code:
... | sed -e "s/^[ \t]*//" | sed -e ':x;$!N;s/\n//;tx'
Dabei ist die zweifache Verwendung von "sed" genauso entscheidend wie die einfachen Hochkommata um die Kommandofolge des zweiten Aufrufs, weil bei der Verwendung von Anführungszeichen (wie beim ersten Aufruf) zusätzliche Maskierungen von Sonderzeichen mit spezieller Bedeutung in Shell-Kommandos erfolgen müßten.
An dieser Stelle ziemlich umsonst ist hingegen die Beschränkung des "N"-Kommandos auf alle Zeilen außer der letzten, da streng genommen ohnehin nur die allererste Zeile "normal" gelesen wird und alle nachfolgenden Zeilen vom "N"-Kommando in den "pattern space" transferiert werden.
Solange man jetzt mit dieser "einzelnen Zeile" als Ergebnis nichts weiter mehr machen will, spielt es auch keine Rolle, wenn das letzte "N"-Kommando dann fehlschlägt und die Abarbeitung der Kommandofolge beendet wird ... damit ist also in diesem konkreten Fall ":x;N;s/\n//;tx" vom Ergebnis her mit der Variante mit dem zusätzlichen "$!" identisch.
Erst wenn hinter dem "t"-Kommando (das ist ja ein "conditional branch", der nur dann ausgeführt wird, wenn es eine Substitution zuvor gab) noch weitere Kommandos folgen (die werden ja dann erst ausgeführt, wenn die einzelne Zeile komplett zusammengezogen wurde und es keine Ersetzung mehr gab - weil es kein "newline" im "pattern space" gibt, solange das "N" nicht ausgeführt wurde), erst dann macht es einen gewaltigen Unterschied, ob man die letzte Zeile mit einbezieht oder nicht. Gewöhnt man sich für das "N"-Kommando gleich an, daß man es besser nicht auf die letzte Zeile losläßt, spart man sich u.U. viel Zeit bei der Fehlersuche.
Man könnte ja das Auslesen der SID auch gleich mit dem Zusammenziehen zu einer Zeile in einem Kommando zusammenfassen (der erste "sed"-Aufruf entfernt nur führende Leerzeichen und Tabulatoren, das könnte man auch nachträglich erst machen):
Code:
sed -e "s/^[ \t]*//" | sed -e ':x;$!N;s/\n//;tx;s|.*<SID>\(.*\)</SID>.*|\1|'
Wenn man dieses Kommando mit und ohne "$!" testet, stellt man den Unterschied fest:
Code:
# echo -n -e "1\n2\n3\n 4<SID>\n\t5\n</SID>6\n7\n" | sed -e "s/^[ \t]*//" | sed -e ':x;$!N;s/\n//;tx;s|.*<SID>\([^\<]*\)</SID>.*|\1|'
5
# echo -n -e "1\n2\n3\n 4<SID>\n\t5\n</SID>6\n7\n" | sed -e "s/^[ \t]*//" | sed -e ':x;N;s/\n//;tx;s|.*<SID>\([^\<]*\)</SID>.*|\1|'
1234<SID>5</SID>67
Im zweiten Falle kommt also das letzte "s"-Kommando gar nicht mehr zur Ausführung, weil der Fehler beim "N" die gesamte Kommandofolge abbricht. Da das Zusammenziehen auch so lange fortgesetzt wird, bis praktisch alles in Zeile 1 steht, spielt hier die Frage, ob die Eingabe nun eine gerade oder eine ungerade Anzahl von Zeilen enthält, keine wirkliche Rolle mehr.
Das hatte zwar mit dem "reboot" an sich jetzt alles nichts mehr zu tun, aber so einfach wie mit den beiden gezeigten "s"-Kommandos von @Riverhopper dürfte das auch wieder nicht funktionieren ... und für den Fall, daß spätere Leser dann auf das gezeigte Kommando zurückgreifen wollen und dabei nicht das erwartete Ergebnis erzielen, konnte ich mir diesem Nachtrag auch wieder nicht verkneifen.