379 votes

Remplacer une ligne entière contenant une chaîne de caractères en utilisant Sed

J'ai un fichier texte qui contient une ligne particulière, du genre

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

Je dois remplacer toute la ligne ci-dessus par

This line is removed by the admin.

Le mot clé de la recherche est TEXT_TO_BE_REPLACED

Je dois écrire un shell script pour cela. Comment puis-je y parvenir en utilisant sed ?

570voto

CodeGnome Points 25402

Vous pouvez utiliser le changement pour remplacer la ligne entière, et la commande -i pour effectuer les changements en place. Par exemple, en utilisant GNU sed :

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

4 votes

Notez que vous avez besoin d'un espace avant le c \. J'ai juste édité pour ajouter ceci.

35 votes

@MarcusDowning GNU sed fait pas nécessitent l'espace ; cela fonctionne très bien tel que posté à l'origine. Si votre sed particulier exige l'espace, alors, par tous les moyens, notez quel sed est incompatible et ajoutez l'invocation nécessaire comme commentaire. Cependant, s'il vous plaît, ne changez pas le code qui fonctionne dans une réponse acceptée.

1 votes

J'ai découvert que le \ après c n'est pas irremplaçable. Sans lui, la commande entière peut fonctionner parfaitement. Il a été ajouté ici pour augmenter la lisibilité ?

179voto

Thor Points 13562

Vous devez utiliser les wildards ( .* ) avant et après pour remplacer la ligne entière :

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

0 votes

Merci, j'ai réussi à faire fonctionner le mien : sed 's/.*<expression>.*/<expression>SE_LABEL = ABC<expression>/g' MYR2.xml > test.txt

13 votes

Cela fonctionne sur Mac OS X Yosemite, sauf que j'utilise les drapeaux -i et -e comme suit : sed -i -e "s/.*search_string.*/Replacement_line/' file_being_searched.txt

1 votes

@KentJohnson Je pense que vous avez des guillemets mal assortis dans votre commande.

25voto

user4256255 Points 311

La réponse ci-dessus :

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

Cela fonctionne bien si la chaîne/ligne de remplacement n'est pas une variable.

Le problème est que sur Redhat 5, l'option \ après le c s'échappe de la $ . Un double \\ ne fonctionne pas non plus (du moins sur Redhat 5).

À force d'essais, j'ai découvert que le \ après le c est redondant si votre chaîne/ligne de remplacement n'est qu'une seule ligne. Je n'ai donc pas utilisé \ après le c J'ai utilisé une variable comme ligne de remplacement unique et c'était la joie.

Le code ressemblerait à quelque chose comme :

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

Notez l'utilisation de guillemets doubles au lieu de guillemets simples.

23voto

skensell Points 33

La réponse acceptée n'a pas fonctionné pour moi pour plusieurs raisons :

  • ma version de sed n'aime pas -i avec une extension de longueur nulle
  • la syntaxe du c\ La commande est bizarre et je n'ai pas réussi à la faire fonctionner.
  • Je n'avais pas réalisé que certains de mes problèmes venaient de barres obliques non cachées.

Voici donc la solution que j'ai trouvée et qui, je pense, devrait fonctionner dans la plupart des cas :

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)
    # FIX: No space after the option i.
    sed -i.bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
    mv "${FILE}.bak" /tmp/
}

Donc l'usage de l'échantillon pour résoudre le problème posé :

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

8voto

b_laoshi Points 355

Toutes les réponses fournies jusqu'à présent supposent que vous connaissez quelque chose au sujet du texte à remplacer, ce qui est logique, puisque c'est ce que le PO a demandé. Je fournis une réponse qui suppose que vous ne savez rien du texte à remplacer et qu'il peut y avoir une ligne distincte dans le fichier avec le même contenu ou un contenu similaire que vous ne voulez pas remplacer. En outre, je suppose que vous connaissez le numéro de la ligne à remplacer.

Les exemples suivants illustrent la suppression ou la modification de texte par des numéros de ligne spécifiques :

# 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/'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X