Je voudrais exécuter une recherche et remplacer sur un fichier HTML via la ligne de commande.
Ma commande ressemble à quelque chose comme ça:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html
Lorsque je lance ceci et que je regarde le fichier par la suite, il est vide. Il a supprimé le contenu de mon dossier.
Quand je lance ceci après avoir restauré le fichier:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
Le stdout
est le contenu du fichier, et la recherche et le remplacement ont été exécutés.
Pourquoi cela arrive-t-il?
Lorsque Shell voit > index.html
dans la ligne de commande, il ouvre le fichier index.html
pour écriture, en effaçant tout son contenu précédent.
Pour résoudre ce problème, vous devez passer l'option -i
à sed
pour effectuer les modifications en ligne et créer une sauvegarde du fichier d'origine avant les modifications sur place:
sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
Sans le .bak, la commande échouera sur certaines plates-formes, telles que Mac OSX.
Un modèle alternatif, utile, est:
sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html
Cela a pratiquement le même effet, sans utiliser l'option -i
, et signifie en outre que, si le script sed échoue pour une raison quelconque, le fichier d'entrée n'est pas compressé. De plus, si l'édition réussit, il ne reste aucun fichier de sauvegarde. Ce genre d'idiome peut être utile dans Makefiles.
Beaucoup de seds ont l'option -i
, mais pas tous; le posix sed est celui qui ne le fait pas. Si vous visez la portabilité, évitez-la.
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html
Cela effectue une substitution globale sur place dans le fichier index.html. La citation de la chaîne évite les problèmes de blancs dans la requête et de remplacement.
utilisez l'option -i de sed, par exemple.
sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
Pour modifier plusieurs fichiers (et enregistrer une sauvegarde de chacun sous le nom * .bak):
Perl -p -i -e "s/\|/x/g" *
va prendre tous les fichiers dans le répertoire et remplacer |
par x
c'est ce qu'on appelle un "camembert Perl" (simple comme bonjour)
Vous devriez essayer d'utiliser l'option -i
pour l'édition sur place.
Attention: il s'agit d'une méthode dangereuse! Il abuse des tampons d'E/S sous Linux et, avec des options spécifiques de mise en tampon, il parvient à fonctionner sur de petits fichiers. C'est une curiosité intéressante. Mais ne l'utilisez pas pour une situation réelle!
Outre l'option -i
de sed
, vous pouvez utiliser l'utilitaire tee
.
De man
:
tee - lit à partir de l'entrée standard et écrit dans la sortie standard et les fichiers
Donc, la solution serait:
sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html
- ici, tee
est répété pour s'assurer que le pipeline est mis en mémoire tampon. Ensuite, toutes les commandes du pipeline sont bloquées jusqu'à ce qu'elles aient une entrée sur laquelle travailler. Chaque commande du pipeline commence lorsque les commandes en amont ont écrit 1 tampon d'octets (la taille est définie quelque part ) dans l'entrée de la commande. Ainsi, la dernière commande tee index.html
, qui ouvre le fichier en écriture et le vide par conséquent, est exécutée une fois le pipeline en amont terminé et que la sortie se trouve dans la mémoire tampon du pipeline.
Très probablement, les éléments suivants ne fonctionneront pas:
sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html
- il lancera les deux commandes du pipeline en même temps sans aucun blocage. (Sans bloquer le pipeline, les octets doivent passer ligne par ligne et non tampon par tampon. Idem que lorsque vous exécutez cat | sed s/bar/GGG/
. Sans le bloquer, il est plus interactif et généralement des pipelines de seulement 2 commandes sont exécutés sans tampon ni blocage. Les pipelines plus longs sont mis en mémoire tampon.) Le tee index.html
ouvrira le fichier en écriture et le videra. Cependant, si vous activez toujours la mise en mémoire tampon, la deuxième version fonctionnera également.
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html
Si vous avez un lien à ajouter, essayez ceci. Recherchez l'URL comme ci-dessus (en commençant par https et finissez par.com ici) et remplacez-la par une chaîne d'URL. J'ai utilisé une variable $pub_url
ici. s
signifie ici recherche et g
signifie remplacement global.
Ça marche !
Le problème avec la commande
sed 'code' file > file
est-ce que file
est tronqué par le shell avant que sed puisse réellement le traiter. En conséquence, vous obtenez un fichier vide.
Pour ce faire, la méthode la plus simple consiste à utiliser -i
pour le modifier à la place, comme suggéré par d'autres réponses. Cependant, ce n'est pas toujours ce que vous voulez. -i
créera un fichier temporaire qui sera ensuite utilisé pour remplacer le fichier d'origine. Ceci est problématique si votre fichier d'origine était un lien (le lien sera remplacé par un fichier normal). Si vous devez conserver des liens, vous pouvez utiliser une variable temporaire pour stocker la sortie de sed avant de l'écrire dans le fichier, comme suit:
tmp=$(sed 'code' file); echo -n "$tmp" > file
Mieux encore, utilisez printf
au lieu de echo
puisque echo
est susceptible de traiter \\
comme \
dans certains shells (par exemple, tiret):
tmp=$(sed 'code' file); printf "%s" "$tmp" > file
Et la ed
répond:
printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html
Pour rappeler ce que réponse codaddict , le shell gère la redirection en premier , en effaçant le fichier "input.html", et puis le shell appelle la commande "sed" en lui transmettant un fichier maintenant vide.
Vous pouvez utiliser Vim en mode Ex:
ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
%
sélectionner toutes les lignes
x
enregistrer et fermer
Je cherchais l'option permettant de définir la plage de lignes et de trouver la réponse. Par exemple, je souhaite remplacer Host1 par Host2 à partir des lignes 36-57.
sed '36,57 s/Host1/Host2/g' myfile.txt > myfile1.txt
Vous pouvez également utiliser l’option gi pour ignorer la casse des caractères.
sed '30,40 s/version/story/gi' myfile.txt > myfile1.txt
En tout respect pour les réponses correctes ci-dessus, il est toujours bon de "sécher" des scripts comme celui-ci, afin de ne pas corrompre votre fichier et de devoir tout recommencer à zéro.
Demandez à votre script de renvoyer la sortie sur la ligne de commande au lieu de l'écrire dans le fichier, par exemple, comme ceci:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
OR
less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g
De cette façon, vous pouvez voir et vérifier le résultat de la commande sans que votre fichier soit tronqué.