440 Stimmen

Ersetzen einer ganzen Zeile mit einer Zeichenkette durch Sed

Ich habe eine Textdatei, die eine bestimmte Zeile enthält, etwa so

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

Ich muss die ganze Zeile oben ersetzen durch

This line is removed by the admin.

Der Suchbegriff lautet TEXT_TO_BE_REPLACED

Ich muss dafür ein Shell-Skript schreiben. Wie kann ich dies erreichen mit sed ?

4voto

Grain Punkte 553

zur Manipulation von Konfigurationsdateien

Ich habe mir diese Lösung ausgedacht, inspiriert durch skensell Antwort

configLine [searchPattern] [replaceLine] [filePath]

wird es:

  • die Datei erstellen, wenn sie nicht existiert
  • die gesamte Zeile (alle Zeilen) ersetzen, in der searchPattern Angepasst
  • hinzufügen. replaceLine am Ende der Datei, wenn das Muster nicht gefunden wurde

Funktion:

function configLine {
  local OLD_LINE_PATTERN=$1; shift
  local NEW_LINE=$1; shift
  local FILE=$1
  local NEW=$(echo "${NEW_LINE}" | sed 's/\//\\\//g')
  touch "${FILE}"
  sed -i '/'"${OLD_LINE_PATTERN}"'/{s/.*/'"${NEW}"'/;h};${x;/./{x;q100};x}' "${FILE}"
  if [[ $? -ne 100 ]] && [[ ${NEW_LINE} != '' ]]
  then
    echo "${NEW_LINE}" >> "${FILE}"
  fi
}

die verrückte Magie des Ausgangsstatus kommt von https://stackoverflow.com/a/12145797/1262663

3voto

Benjamin W. Punkte 37771

Um dies zu tun, ohne sich auf irgendwelche GNUismen wie -i ohne einen Parameter oder c ohne einen Zeilenumbruch:

sed '/TEXT_TO_BE_REPLACED/c\
This line is removed by the admin.
' infile > tmpfile && mv tmpfile infile

In dieser (POSIX-kompatiblen) Form des Befehls

c\
text

text kann aus einer oder mehreren Zeilen bestehen, und Zeilenumbrüche, die Teil der Ersetzung werden sollen, müssen ausgeschnitten werden:

c\
line1\
line2
s/x/y/

donde s/x/y/ ist ein neuer sed-Befehl, nachdem das Musterleerzeichen durch die beiden Zeilen ersetzt worden ist

line1
line2

2voto

Martin Pfeffer Punkte 11992

In meinem Makefile verwende ich dies:

@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md

PS: NICHT Vergessen Sie nicht, dass -i den Text in der Datei ändert. Wenn sich also das Muster, das Sie als "Revision" definiert haben, ändert, ändern Sie auch das zu ersetzende Muster.

Beispielhafte Ausgabe:

Abc-Projekt geschrieben von John Doe

Revision: 1190

Wenn Sie also das Muster "Revision: 1190" festlegen, ist das offensichtlich nicht dasselbe wie wenn Sie sie nur als "Revision:" definieren...

2voto

nkl Punkte 21
bash-4.1$ new_db_host="DB_HOSTNAME=good replaced with 122.334.567.90"
bash-4.1$ 
bash-4.1$ sed -i "/DB_HOST/c $new_db_host" test4sed
vim test4sed
'
'
'
DB_HOSTNAME=good replaced with 122.334.567.90
'

es funktioniert gut

2voto

sorpigal Punkte 24323

In der Frage wird nach Lösungen gefragt, die sed Wenn das aber keine zwingende Voraussetzung ist, gibt es eine andere Möglichkeit, die vielleicht die bessere Wahl ist.

Die akzeptierte Antwort lautet sed -i und beschreibt es als Ersetzen der Datei an Ort und Stelle, aber -i tut das nicht wirklich und macht stattdessen das Äquivalent von sed pattern file > tmp; mv tmp file , die Erhaltung des Eigentums und der Modalitäten. Dies ist unter vielen Umständen nicht ideal. Im Allgemeinen empfehle ich nicht die Ausführung von sed -i nicht-interaktiv als Teil eines automatischen Prozesses - es ist, als würde man eine Bombe mit einer Lunte unbekannter Länge zünden. Früher oder später wird sie bei jemandem hochgehen.

Um eine Datei tatsächlich "an Ort und Stelle" zu bearbeiten und eine Zeile, die einem Muster entspricht, durch einen anderen Inhalt zu ersetzen, sollten Sie einen echten Texteditor verwenden. So wird es gemacht mit ed , dem Standard-Texteditor.

printf '%s\n' '/TEXT_TO_BE_REPLACED/' d i 'This line is removed by the admin' . w q | \
ed -s /tmp/foo > /dev/null

Beachten Sie, dass dies nur die erste Das ist das, was die Frage impliziert hat und was gewünscht wurde. Dies ist ein wesentlicher Unterschied zu den meisten anderen Antworten.

Abgesehen von diesem Nachteil gibt es einige Vorteile bei der Verwendung von ed über sed :

  • Sie können die Übereinstimmung ohne zusätzlichen Aufwand durch eine oder mehrere Zeilen ersetzen.
  • Der Ersetzungstext kann beliebig komplex sein, ohne dass er durch ein Escaping geschützt werden muss.
  • Am wichtigsten ist, dass die Originaldatei geöffnet, geändert und gespeichert wird. Eine Kopie wird nicht erstellt.

Wie es funktioniert

Wie es funktioniert:

  • printf verwendet sein erstes Argument als Formatzeichenfolge und druckt jedes seiner anderen Argumente unter Verwendung dieses Formats, was bedeutet, dass jedes Argument von printf zu einer Ausgabezeile wird, die alle an ed auf stdin.
  • Die erste Zeile ist eine Regex-Musterübereinstimmung, die ed dazu veranlasst, seine Vorstellung von "der aktuellen Zeile" auf die erste übereinstimmende Zeile zu verschieben (wenn es keine Übereinstimmung gibt, wird die aktuelle Zeile auf die letzte Zeile der Datei gesetzt).
  • Die nächste ist die d Befehl, der anweist ed um die gesamte aktuelle Zeile zu löschen.
  • Danach kommt die i Befehl, der die ed in den Einfügemodus;
  • Danach werden alle nachfolgenden Zeilen in die aktuelle Zeile geschrieben (oder in zusätzliche Zeilen, wenn es eingebettete Zeilenumbrüche gibt). Das bedeutet, dass Sie eine Variable erweitern können (z.B. "$foo" ), die mehrere Zeilen enthält, und es werden alle eingefügt.
  • Der Einfügemodus endet, wenn ed sieht eine Linie bestehend aus .
  • En w schreibt den Inhalt der Datei auf die Festplatte, und
  • el q Befehl wird beendet.
  • En ed wird der Befehl -s und schaltet ihn in einen stillen Modus, so dass er während der Ausführung keine Informationen ausgibt,
  • wird die zu bearbeitende Datei als Argument an ed ,
  • und schließlich wird stdout weggeworfen, um zu verhindern, dass die Zeile, die mit der Regex übereinstimmt, gedruckt wird.

Einige Unix-ähnliche Systeme werden (unpassenderweise) ohne eine ed installiert, aber möglicherweise noch mit einer ex Wenn dies der Fall ist, können Sie es einfach stattdessen verwenden. Wenn haben vim aber keine ex o ed können Sie vim -e stattdessen. Wenn Sie nur über Standard vi aber keine ex o ed beschweren Sie sich bei Ihrem Sysadmin.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X