Remplacer la ligne entière contenant une chaîne en utilisant Sed
j'ai un fichier texte qui a une ligne particulière quelque chose comme
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 recherche est TEXT_TO_BE_REPLACED
j'ai besoin d'écrire un script shell pour cela. Comment réaliser cela en utilisant sed
?
10 réponses
vous pouvez utiliser la commande change pour remplacer la ligne entière, et le drapeau -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
vous devez utiliser wildards ( .*
) avant et après pour remplacer la ligne entière:
sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'
Les accepté de répondre ne fonctionne pas pour moi pour plusieurs raisons:
- ma version de sed n'aime pas
-i
avec une extension zéro longueur - la syntaxe de la commande
c\
est étrange et je n'ai pas pu la faire fonctionner - Je n'avais pas réalisé que certains de mes problèmes venaient de slashes sans issue
voici donc la solution que j'ai trouvée et qui devrait fonctionner pour la plupart des cas:
function escape_slashes {
sed 's/\//\\//g'
}
function change_line {
local OLD_LINE_PATTERN=; shift
local NEW_LINE=; shift
local FILE=
local NEW=$(echo "${NEW_LINE}" | escape_slashes)
sed -i .bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
mv "${FILE}.bak" /tmp/
}
ainsi l'utilisation de l'échantillon pour résoudre le problème posé:
change_line "TEXT_TO_BE_REPLACED" "This line is removed by the admin." yourFile
La Réponse ci-dessus:
sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
fonctionne très bien si la chaîne/ligne de remplacement n'est pas une variable.
le problème est que sur Redhat 5 Le \
après le c
échappe au $
. Un double \
ne fonctionnait pas non plus (du moins sur Redhat 5).
par hit and trial, j'ai découvert que le \
après le c
est redondant si votre chaîne/ligne de remplacement est seulement une seule ligne. Donc, je n'ai pas utilisé \
après le c
, utilisé une variable comme une ligne de remplacement simple et il était de la joie.
le code ressemblerait à quelque chose comme:
sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo
Remarque l'utilisation de guillemets au lieu de guillemets simples.
dans mon makefile j'utilise ceci:
@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md
PS: NE PAS oubliez pas que l'-je change réellement le texte dans le fichier... donc, si le modèle que vous avez défini comme "Révision" va changer, vous aurez également changer le motif à remplacer.
exemple de sortie:
Abc-projet écrit par John Doe
révision: 1190
donc si vous définissez le motif " révision: 1190 "ce n'est évidemment pas la même chose que vous les avez définis comme" révision: "seulement...
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
'
il fonctionne très bien
toutes les réponses fournies jusqu'à présent supposent que vous savez quelque chose sur le texte à remplacer qui a du sens, puisque c'est ce que l'OP a demandé. Je fournis une réponse qui suppose que vous ne savez rien sur le texte à remplacer et qu'il peut y avoir une ligne séparée dans le fichier avec le même contenu ou similaire que vous ne voulez pas être remplacé. De plus, je suppose que vous connaissez le numéro de ligne de la ligne à remplacer.
les exemples suivants démontrer la suppression ou la modification du 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/'
cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file
done
fichier find_replace contient 2 colonnes, c1 avec motif à apparier, c2 avec remplacement, la boucle sed remplace chaque ligne contenant l'un des motifs de la variable 1
il est aussi similaire à celui ci-dessus..
sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'
j'utilise très souvent regex pour extraire des données à partir de fichiers que je viens d'utiliser pour remplacer la citation littérale \"
par //
rien: -)
cat file.csv | egrep '^\"([0-9]{1,3}\.[0-9]{1,3}\.)' | sed s/\"//g | cut -d, -f1 > list.txt