2017-01-04 13 views
0

Ich versuchte Befehl sed 's/$/\r/g' linux.txt > linux2win.txt, um die Textdatei von Linux zu Windows zu konvertieren.Wie funktioniert dieser sed Befehl?

Und es funktioniert! alle \n-\r\n

zum Beispiel umgewandelt werden, hello, world \n-hello, world \r\n umgewandelt wird

Was mich verwirrt ist, was genau $ bezieht sich auf? \n? oder ein leeres Zeichen vor \n? Ich weiß nicht einmal, was ich ersetzt habe.

+0

Dies könnte helfen: [Die häufigen Fragen zu Stack Overflow Regular Expressions] (http://stackoverflow.com/a/22944075/3776858) – Cyrus

+0

Dieser Befehl macht das Gegenteil von dem, was Sie sagen. – melpomene

+1

Mögliches Duplikat von [Dollarzeichen in regulärem Ausdruck und neuem Zeilenzeichen] (http://stackoverflow.com/questions/13912373/dollar-sign-in-regular-expression-and-new-line-character) – Cyrus

Antwort

0

Die Antworten/Kommentare bisher, dass $ das Ende der Zeile übereinstimmt, sind irreführend. $ in einem Regexp entspricht Ende der Zeichenfolge, das ist alles. Der Grund, warum erscheint, um das Ende der Zeile in sed zu entsprechen, ist, dass sed standardmäßig 1 Zeile gleichzeitig liest, so dass in diesem Kontext (aber nicht in anderen) jede Zeile am Ende der Zeile endet.

So $ Matches End-of-String und wenn die Zeichenfolge enden am Ende einer Zeile dann $ Begegnungen am Ende der Zeile, aber wenn die Zeichenfolge enthält mehrere Zeilen (zB in sed Sie eine mehrzeilige erstellen String in einem Puffer gespeichert) dann passt $ nicht am Ende einer gegebenen Zeile, es entspricht einfach und konsistent am Ende der Zeichenfolge.

In ähnlicher Weise ^ entspricht Start-of-String, BTW, nicht Start-of-Line, wie Sie vielleicht Menschen behaupten hören.

WRT Ihr Kommentar:

my original line is hello, world \n$ and $ is invisible , and $ is replaced by \r, now my line is hello, world\n\r$ .` 

Nein, das ist nicht, was geschieht. Ihre ursprüngliche Linie ist:

hello, world\n 

und sed liest man \n -separated Linie zu einer Zeit, so was in seds Puffer gelesen wird, wird die Zeichenfolge:

hello, world 

Jetzt $ ist ein regexp metacharacter, dass die Spiele End-of-string so die obige Zeichenfolge gegeben $ nach dem Spiel wird d (und ^ würde vor h entsprechen) so, wenn Sie tun

s/$/\r/ 

Es ändert sich die obige Zeichenfolge:

hello world\r 

und dann druckt es, wenn Sed heraus es fügt die Newline zurück und Ausgänge (weil eine Zeichenfolge ohne das abschließende Newline nicht eine Textzeile pro POSIX ist):

hello world\r\n 

Beachten Sie, dass $ nie Teil der Zeichenfolge ist, es ist nur ein Metazeichen, dass, wenn in einem regulären Ausdruck entspricht das Ende der Zeichenfolge verwendet, so dass Sie für Zeichen testen können nur am Ende eines Strings oder tun andere erscheinen Operationen (wie oben) nach dem Ende der Zeichenfolge.

+1

Danke! Diese Antwort hilft mir wirklich! Ich wusste nicht, dass sed ein '\ n' konsumieren würde. Ohne deine Antwort werde ich '$' in Regexp für eine lange Zeit missverstehen. – PYL

0

$ entspricht dem Ende der Zeile, so dass der Befehl:

sed 's/$/\r/g' 

fügt einfach \r bis zum Ende der Linie, die ist nicht was Sie sagen. Wenn die Eingabe "Hallo, Welt \ r \ n" lautet, lautet die Ausgabe "Hallo, Welt \ r \ n".

+0

@PYL Der Befehl "fügt" einfach "\ r" an das Zeilenende an (er ersetzt den "letzten Platz" tatsächlich durch "\ r"). – Maroun

+0

Ich denke auf diese Weise: meine ursprüngliche Zeile ist Hallo, Welt \ n $ und $ ist unsichtbar, und $ wird durch \ r ersetzt, jetzt ist meine Zeile Hallo, Welt \ n \ r $. Es ist komisch, oder? – PYL

+1

mit 'Wenn die Eingabe" Hallo, Welt \ r \ n "ist, würde die Ausgabe" Hallo, Welt \ r \ n "' lauten - das hängt von der Umgebung ab, in der Sie ausgeführt werden und ob die zugrunde liegenden C-Primitiven vorhanden sind Lassen Sie das '\ r' von der Eingabe durch 'sed' gehen. Wenn Sie beispielsweise mit sed im Binärmodus auf cygwin laufen würden, wäre die Ausgabe "Hallo, Welt \ r \ r \ n" ' –

0

Die Prämisse Ihrer Frage ist fehlerhaft. Der sed Befehl, den Sie präsentieren, konvertiert Zeilenbegrenzer im Linux-Stil (nur Newline) in Windows-Stil (Wagenrücklauf/Zeilenumbruch), nicht umgekehrt.

Es funktioniert wie folgt:

  • die $ ein regex metacharacter ist, dass die Null-Breite Ende der Leitung übereinstimmt (das heißt unmittelbar vor dem Leitungsabschluss, falls vorhanden).
  • Die Ersetzungszeichenfolge ist ein Wagenrücklaufzeichen (ausgedrückt als \r); sie ersetzt die Null-Breite durch den regulären Ausdruck in der Tat angepaßten Zeichensequenz sofort den Wagenrücklauf vor dem Einsetzen newline

Die g in der SED-Befehl gibt an, dass alle Hintereinstimmungen in jeder Zeile ersetzt werden sollte; Es ist überflüssig, weil es nicht mehr als eine Übereinstimmung pro Zeile geben kann.

Beachten Sie auch, dass dies etwas schrullig sein kann: Wenn die Eingabedatei nicht mit einem Zeilenumbruch endet, endet die Ausgabe nur mit \r, weil das Ende der Datei dann das Ende der letzten Zeile ist.

+0

Ich denke auf diese Weise: Meine ursprüngliche Zeile ist Hallo, Welt \ n $ und $ ist unsichtbar, und $ wird durch \ r ersetzt, jetzt ist meine Zeile Hallo, Welt \ n \ r $. Es ist komisch, oder? – PYL

+0

Nein, @PYL, es ist überhaupt nicht komisch. Die Zeilenumbrüche in der Eingabedatei werden nicht als * Teil von * den Zeilen von 'sed' betrachtet. Sie sind Zeilenabschlüsse - die Zeile endet kurz vor und die nächste Zeile beginnt gleich danach. 'sed' verwendet Zeilenabschlüsse bei der Eingabe und (standardmäßig) neue bei der Ausgabe. Sie können Zeilenumbrüche in den 'sed'-Musterraum auf andere Weise erhalten, aber Sie erhalten sie nicht durch einfaches Lesen einer Linie in den Musterraum. –

+0

Danke! Hilft mir sehr! – PYL