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.

Sas
quelle

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).

AB
quelle
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.

unxnut
quelle
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
cuonglm
quelle
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
αғsнιη
quelle
$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
don_crissti
quelle
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

~ $
k_vishwanath
quelle
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'
Benamar
quelle