So ersetzen Sie ein Wort durch eine neue Zeile


11

Ich habe eine Textdatei mit folgenden Daten und jede Zeile endet mit |END|.

T|somthing|something|END|T|something2|something2|END|

Ich tryig ersetzen |END|mit \nneuer Linie mit sed.

 sed 's/\|END\|/\n/g' test.txt

Aber es erzeugt eine falsche Ausgabe wie unten:

 T
 |
 s
 o
 m
 e
 ...

Aber was ich will ist folgendes:

T|somthing|something
T|something2|something2

Ich habe es auch mit versucht tr. Es hat auch nicht funktioniert.


Antworten:


15

Benutze das:

sed 's/|END|/\n/g' test.txt

Was Sie versucht haben, funktioniert nicht, weil sed grundlegende reguläre Ausdrücke verwendet und Ihre sed-Implementierung einen \|Operator hat, der "oder" bedeutet (eine häufige Erweiterung von BRE). Das, was Sie geschrieben haben, wird also ENDdurch eine neue Zeile ersetzt (leere Zeichenfolge oder leere Zeichenfolge).


Müssen die \ in \ n: sed 's / | END | / \\ n / g
Baazigar

@ Baazigar Nein, was AB geschrieben hat, ist korrekt (zumindest für Linux würden einige sed-Implementierungen emittieren \n). In der Frage wird gefragt, wie |END|durch eine neue Zeile ersetzt werden soll, nicht durch \n.
Gilles 'SO - hör auf böse zu sein'

Die Zeichen für Zeilenumbruch sind '\ n'. Das \\ n wird benötigt, da \ auch ein Escape-Zeichen ist. Wenn Sie also nur \ n tun, sagen Sie 'Escape this n-Zeichen'. Wenn Sie dies tun, sagen Sie "Behandeln Sie das nächste Mal nicht als Flucht".
Baazigar

7

Folgendes hat für mich gut funktioniert:

$ sed 's/|END|/\
/g' foobar
T|somthing|something
T|something2|something2

Beachten Sie, dass ich nur einen Backslash gefolgt von der Eingabetaste eingefügt habe.


2
Das ist die Standardsyntax. Die Verwendung \n wie in der Antwort von @ AB würde bei einigen sedImplementierungen nicht funktionieren .
Stéphane Chazelas

@ StéphaneChazelas Welche sed-Implementierung unterstützt den \|Wechsel in einem regulären Ausdruck, \nbedeutet aber nicht newline in einem sErsatz?
Gilles 'SO - hör auf böse zu sein'

5

Sie können verwenden awk:

$ awk -F'\\|END\\|' '{$1=$1}1' OFS='\n' file
T|somthing|something
T|something2|something2
  • -F'\\|END\\|' Feldtrennzeichen auf setzen |END|
  • OFS='\n' Setzen Sie das Ausgabefeldtrennzeichen auf newline
  • $1=$1Ursache awkRekonstruktion $0mit OFSals Feldtrennzeichen
  • 1ist ein wahrer Wert, da awkdie gesamte Eingabezeile gedruckt wird

3

Ein anderer möglicherweise Befehl, der seine RSOption verwendet, wäre:

awk '$1=$1' RS="\|END\|" file

Werden die Datensätze gedruckt werden (basierend auf awk des R ecord S eparator) , die nicht leer sind (mindestens ein Feld) Drucken Leerzeilen zu verhindern.

Getestet an diesem Eingang:

T|somthing|something|END|T|something2|something2|END|
Test|END|
|END|

Gibt diese Ausgabe:

T|somthing|something
T|something2|something2
Test

Damit wurden alle Leerzeilen gelöscht :) Wenn Sie auch Zeilenumbrüche wünschen, ersetzen Sie diese $1=$1durch den $0Befehl in:

awk '$0' RS="\|END\|" file

$1=$1komprimiert Leerzeichenfolgen zu einem Leerzeichen und gibt false zurück, wenn das erste Feld 0 ist. Das macht keinen Sinn. Sie wollen wahrscheinlich awk 1 RS='\\|END\\|'oder awk NF RS='\\|END\\|'oder awk length RS='\\|END\\|'hier. Beachten Sie, dass ein Regexp RS Gawk oder Mawk erfordert
Stéphane Chazelas

3

Ein anderer Weg, bei seddem keine leeren Zeilen gedruckt werden:

sed 's/|END|/\
/g;/^$/!P;D' infile

zB Eingabe:

T|one|two|END|T|three|four|END|
T|five|six|END|T|seven|eight|END|
T|nine|ten|END|T|eleven|twelve|END|

Ausgabe:

T|one|two
T|three|four
T|five|six
T|seven|eight
T|nine|ten
T|eleven|twelve

das Gleiche mit ed:

ed -s infile <<'IN'
1,$j
s/|END|/\
/g
,p
q
IN

1

Wie hier von Walter Mundt erwähnt , können wir dies mit einer ANSI C-Zeichenfolge erreichen

sed $'s/|END|/\\\n/g'

~ $ echo 'T|somthing|something|END|T|something2|something2|END|' | sed 
$'s/|END|/\\\n/g'
T|somthing|something
T|something2|something2

~ $

Weitere Alternativen finden Sie unter dem obigen Link.

Sie können auch die folgende Syntax verwenden. Ich bin mir nicht sicher, ob sie unter allen Unix / Linux-Varianten funktioniert

sed 's/|END|/\'$'\n''/g'

~ $ echo 'T|somthing|something|END|T|something2|something2|END|' | sed 
's/|END|/\'$'\n''/g'
T|somthing|something
T|something2|something2

~ $

Arbeiten an FreeBSD v10. Eigentlich nur Methode, die bei mir funktioniert hat. Danke.
Sopalajo de Arrierez

0

Ich hatte das gleiche Problem in der strengen Posix-Shell, das ich in zwei Durchgängen mit einem nicht verwendeten Zeichen gemacht habe

cat data.json|tr '§' '?'|sed -e 's/"[^"]":/§&/g'|tr '§' '\n'
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.