Wie ersetze ich mehrere Zeilen durch ein einzelnes Wort in der Datei (anstelle von ersetzen)?

9

Der Inhalt meiner filenameDatei ist wie folgt (zum Beispiel):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

Ich möchte einen Zeilenblock zwischen STARTund ENDdurch nur ein einziges Wort ersetzen , zum Beispiel durch SINGLEWORD. Wie unten:

My block of line starts from here 
SINGLEWORD
and end to here for example.

Mit diesem Befehl kann ich meinen Zeilenblock finden:

grep -Pzo "START(.|\n)*END" filename

Das Ergebnis der Ausführung des obigen Befehls lautet wie folgt:

START
First line
second line
third line
END

Dann habe ich diesen Befehl verwendet, um alle Zeilen in einer einzigen Zeile zu kombinieren:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

Dann bekomme ich folgendes Ergebnis:

START First line second line third line END

Und mit meinem letzten Befehl LAST_RESULTS | sed 's/.*/SINGLEWORD/'ändere ich sie in "SINGLEWORD"und erhalte dieses Ergebnis.

SINGLEWORD

Was ich jetzt möchte, ist: Wie kann ich diesen Befehl (oder Ihren Vorschlagsbefehl) verwenden und meinen Zeilenblock (an Ort und Stelle) durch das Wort "SINGLEWORD" ersetzen? Und das Endergebnis wird wie folgt aussehen:

My block of line starts from here 
SINGLEWORD
and end to here for example.
αғsнιη
quelle

Antworten:

14

Dies kann sehr einfach durchgeführt werden in perl:

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

Erläuterung

-0 setzt das Zeilentrennzeichen auf null

-pWenden Sie das von gegebene Skript -eauf jede Zeile an und drucken Sie diese Zeile aus

Der Regexp-Modifikator:

  • /sZeichenfolge als einzelne Zeile behandeln. Das heißt, ändern Sie ., um mit jedem Zeichen übereinzustimmen, auch mit einer neuen Zeile, die normalerweise nicht übereinstimmt.

Warum die ?:

  • Standardmäßig ist ein quantifiziertes Untermuster "gierig", dh es stimmt so oft wie möglich überein (bei einem bestimmten Startort), während der Rest des Musters weiterhin übereinstimmt. Wenn Sie möchten, dass es so wenig wie möglich übereinstimmt, folgen Sie dem Quantifizierer mit a ?.
Sylvain Pineau
quelle
@ KasiyA: Verwenden sedsollte möglich sein, aber wahrscheinlich schwerer zu lesen ( siehe diese Frage )
Sylvain Pineau
Ein weiter , weil mein START und END - Muster hat Sonderzeichen ( /, *, ?) darin , und diese sind nur Beispiel. und könnten Sie Ihren Befehl erklären.
αғsнιη
@KasiyA können Sie solche Escape - Zeichen mit \ (genau wie bei sed): \/, \*,\?
Sylvain Pineau
@ KasiyA Ich habe es versucht perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. Es sollte funktionieren
Sylvain Pineau
@ KasiyA Ich denke, ich bin jetzt mit Erklärungen fertig;)
Sylvain Pineau
14

Ich frage mich , ob dies möglich ist , ohne perl, pythonund andere. Und ich fand diese Lösung mit sed:

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

Erläuterung:

  1. : a Erstelle ein Label 'a'
  2. N Fügen Sie die nächste Zeile an den Musterbereich an
  3. $! wenn nicht die letzte Zeile , ba Zweig (go to) Label 'a'
  4. s Ersatz , /START.*END/durch SINGLEWORD, / g globales Spiel (so oft wie möglich)

Es wurde hier gefunden .

@ KasiyA, danke, ich habe viele interessante Dinge gelernt!

c0rp
quelle