it-swarm.com.de

Ersetzen Sie die gesamte Zeile, die eine Zeichenfolge enthält, mit Sed

Ich habe eine Textdatei, die so etwas wie eine bestimmte Zeile hat

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

Ich muss die gesamte obige Zeile durch ersetzen

This line is removed by the admin.

Das Suchwort lautet TEXT_TO_BE_REPLACED

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

279
Rahul

Sie können den Befehl change verwenden, um die gesamte Zeile zu ersetzen, und das Flag -i, um die Änderungen zu übernehmen. Zum Beispiel mit GNU sed:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
433
Todd A. Jacobs

Sie müssen Wildards (.*) vor und nach dem Ersetzen der gesamten Zeile verwenden:

sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'
131
Thor

Die akzeptierte Antwort hat bei mir aus mehreren Gründen nicht funktioniert:

  • meine Version von sed mag -i nicht mit einer Nulllängenerweiterung
  • die Syntax des c\ -Befehls ist komisch und ich konnte es nicht zum Laufen bringen
  • Ich habe nicht bemerkt, dass einige meiner Probleme von ungeschützten Schrägstrichen herrühren

Hier ist die Lösung, die ich mir ausgedacht habe und die meiner Meinung nach in den meisten Fällen funktionieren sollte:

function escape_slashes {
    sed 's/\//\\\//g' 
}

function change_line {
    local OLD_LINE_PATTERN=$1; shift
    local NEW_LINE=$1; shift
    local FILE=$1

    local NEW=$(echo "${NEW_LINE}" | escape_slashes)
    sed -i .bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
    mv "${FILE}.bak" /tmp/
}

Die Beispielnutzung zur Behebung des Problems stellte sich also wie folgt dar:

change_line "TEXT_TO_BE_REPLACED" "This line is removed by the admin." yourFile
17
skensell

Die Antwort oben:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

Funktioniert einwandfrei, wenn die Ersatzzeichenfolge/-zeile keine Variable ist.

Das Problem ist, dass auf Redhat 5 der \ nach dem c dem $ entgeht. Ein doppeltes \\ funktionierte ebenfalls nicht (zumindest auf Redhat 5).

Durch Treffer und Versuch entdeckte ich, dass der \ nach dem c redundant ist, wenn Ihre Ersatzzeichenfolge/-zeile nur eine einzelne Zeile ist. Also habe ich \ nicht nach c verwendet, eine Variable als einzelne Ersetzungszeile verwendet und es war eine Freude.

Der Code würde ungefähr so ​​aussehen:

sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo

Beachten Sie die Verwendung von doppelten Anführungszeichen anstelle von einfachen Anführungszeichen.

13
user4256255

Bei allen bisherigen Antworten wird davon ausgegangen, dass Sie etwas über den zu ersetzenden Text wissen, was sinnvoll ist, da dies vom OP gefordert wurde. Ich gebe eine Antwort, die davon ausgeht, dass Sie nichts über den zu ersetzenden Text wissen und dass die Datei möglicherweise eine separate Zeile mit demselben oder einem ähnlichen Inhalt enthält, den Sie nicht ersetzen möchten. Außerdem gehe ich davon aus, dass Sie die Zeilennummer der zu ersetzenden Zeile kennen.

Die folgenden Beispiele veranschaulichen das Entfernen oder Ändern von Text durch bestimmte Zeilennummern:

# replace line 17 with some replacement text and make changes in file (-i switch)
# the "-i" switch indicates that we want to change the file. Leave it out if you'd
#   just like to see the potential changes output to the terminal window.
# "17s" indicates that we're searching line 17
# ".*" indicates that we want to change the text of the entire line
# "REPLACEMENT-TEXT" is the new text to put on that line
# "PATH-TO-FILE" tells us what file to operate on
sed -i '17s/.*/REPLACEMENT-TEXT/' PATH-TO-FILE

# replace specific text on line 3
sed -i '3s/TEXT-TO-REPLACE/REPLACEMENT-TEXT/'
3
b_laoshi

zur Manipulation von Konfigurationsdateien

ich habe diese Lösung gefunden, inspiriert von Skensell-Antwort

configLine [searchPattern] [replaceLine] [filePath]

es wird:

  • erstellen Sie die Datei, falls sie nicht vorhanden ist
  • ersetzen Sie die gesamte Zeile (alle Zeilen), wobei searchPattern übereinstimmt
  • fügen Sie replaceLine am Ende der Datei hinzu, 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 Exit-Status-Magie kommt von https://stackoverflow.com/a/12145797/126266

2
Grain

In meinem Makefile verwende ich folgendes:

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

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

Beispielausgabe:

Abc-Projekt geschrieben von John Doe

Revision: 1190

Wenn Sie also das Muster "Revision: 1190" festlegen, ist es offensichtlich nicht dasselbe, wie Sie es nur als "Revision:" definiert haben ...

1
Martin Pfeffer
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

1
nkl
cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file    
done 

die find_replace-Datei enthält 2 Spalten, c1 mit übereinstimmendem Muster, c2 mit Ersetzung. Die sed-Schleife ersetzt jede Zeile, die eines der Muster der Variablen 1 enthält

1
sjordi

Es ist so ähnlich wie oben.

sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'
0