Comment trouver et remplacer des mots spécifiques dans un fichier texte à l'aide de la ligne de commande?
sed -i 's/original/new/g' file.txt
Explication:
sed
= Editeur de flux-i
= in-situ (c'est-à-dire sauvegarder dans le fichier d'origine)La chaîne de commande:
s
= la commande de substitutionoriginal
= une expression rationnelle décrivant le mot à remplacer (ou simplement le mot lui-même)new
= le texte avec lequel le remplacerg
= global (c'est-à-dire tout remplacer et pas seulement la première occurrence)file.txt
= le nom du fichier
Il y a différentes façons de le faire. On utilise sed
et Regex. SED est un éditeur de flux permettant de filtrer et de transformer du texte. Un exemple est le suivant:
marco@imacs-suck: ~$ echo "The slow brown Unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown Unicorn jumped over the hyper sleeping dog
Une autre manière qui peut avoir plus de sens que < strin
et > strout
est d'utiliser des pipes!
marco@imacs-suck: ~$ cat yarly | sed s/Unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai
The quick brown fox jumped over the lazy sleeping dog
Grâce à la commande gsub de awk,
awk '{gsub(/pattern/,"replacement")}' file
Exemple:
awk '{gsub(/1/,"0");}' file
Dans l'exemple ci-dessus, tous les 1 sont remplacés par des 0 quelle que soit la colonne où ils se trouvent.
Si vous voulez remplacer une colonne en particulier, procédez comme suit:
awk '{gsub(/pattern/,"replacement",column_number)}' file
Exemple:
awk '{gsub(/1/,"0",$1);}' file
Il remplace 1 par 0 sur la première colonne uniquement.
À travers Perl,
$ echo 'foo' | Perl -pe 's/foo/bar/g'
bar
Vous pouvez utiliser Vim en mode Ex:
ex -s -c '%s/OLD/NEW/g|x' file
%
sélectionner toutes les lignes
s
substitute
g
remplace toutes les instances de chaque ligne
x
écrire si des modifications ont été apportées (ils l’ont fait) et quitter
Il y a une multitude de façons de le réaliser. En fonction de la complexité de l'objectif recherché avec le remplacement de chaîne et des outils connus de l'utilisateur, certaines méthodes peuvent être préférées à d'autres.
Dans cette réponse, j'utilise un simple fichier input.txt
, que vous pouvez utiliser pour tester tous les exemples fournis ici. Le contenu du fichier:
roses are red , violets are blue
This is an input.txt and this doesn't rhyme
Bash n'est pas vraiment destiné au traitement de texte, mais de simples substitutions peuvent être effectuées via expansion des paramètres , en particulier nous pouvons utiliser une structure simple ${parameter/old_string/new_string}
.
#!/bin/bash
while IFS= read -r line
do
case "$line" in
*blue*) printf "%s\n" "${line/blue/Azure}" ;;
*) printf "%s\n" "$line" ;;
esac
done < input.txt
Ce petit script ne fait pas de remplacement sur place, ce qui signifie que vous devez enregistrer le nouveau texte dans un nouveau fichier et vous débarrasser de l'ancien fichier, ou mv new.txt old.txt
Note latérale: si vous êtes curieux de savoir pourquoi while IFS= read -r ; do ... done < input.txt
est utilisé, c'est en gros la façon dont Shell lit les fichiers ligne par ligne. Voir this pour référence.
AWK, étant un utilitaire de traitement de texte, convient parfaitement à cette tâche. Il peut faire des remplacements simples et beaucoup plus avancés basés sur expressions régulières . Il fournit deux fonctions: sub()
et gsub()
. Le premier ne remplace que la première occurrence, tandis que le second - remplace les occurrences dans la chaîne entière. Par exemple, si nous avons la chaîne one potato two potato
, le résultat serait:
$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana
$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'
one banana two potato
AWK peut prendre un fichier d'entrée comme argument. Il serait donc facile de faire la même chose avec input.txt
:
awk '{sub(/blue/,"Azure")}1' input.txt
Selon la version d'AWK que vous possédez, il est possible que l'édition in-situ ne soit pas activée. Par conséquent, la pratique habituelle consiste à enregistrer et remplacer le nouveau texte. Par exemple, quelque chose comme ceci:
awk '{sub(/blue/,"Azure")}1' input.txt > temp.txt && mv temp.txt input.txt
Sed est un éditeur de ligne. Il utilise également des expressions régulières, mais pour de simples substitutions, il suffit de faire:
sed 's/blue/Azure/' input.txt
L'avantage de cet outil est qu'il dispose d'une édition sur place, que vous pouvez activer avec l'indicateur -i
.
Perl est un autre outil souvent utilisé pour le traitement de texte, mais il s’agit d’un langage généraliste utilisé dans les réseaux, l’administration système, les applications de bureau, etc. Il a emprunté beaucoup de concepts/fonctionnalités d'autres langages tels que C, sed, awk et autres. La substitution simple peut être faite comme suit:
Perl -pe 's/blue/Azure/' input.txt
Comme sed, Perl a également le drapeau -i.
Ce langage est très polyvalent et est également utilisé dans une grande variété d'applications. Il a beaucoup de fonctions pour travailler avec des chaînes, parmi lesquelles replace()
, donc si vous avez une variable comme var="Hello World"
, vous pourriez faire var.replace("Hello","Good Morning")
Un moyen simple de lire le fichier et de remplacer la chaîne est le suivant:
python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','Azure')" < input.txt
Cependant, avec Python, vous devez également générer le nouveau fichier, ce que vous pouvez également créer à partir du script lui-même. Par exemple, voici un exemple simple:
#!/usr/bin/env python
import sys
import os
import tempfile
tmp=tempfile.mkstemp()
with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
for line in fd1:
line = line.replace('blue','Azure')
fd2.write(line)
os.rename(tmp[1],sys.argv[1])
Ce script doit être appelé avec input.txt
comme argument de ligne de commande. La commande exacte pour exécuter le script python avec un argument de ligne de commande serait
$ ./myscript.py input.txt
ou
$ python ./myscript.py input.txt
Bien sûr, assurez-vous que ./myscript.py
est dans votre répertoire de travail actuel et pour la première façon, assurez-vous qu’il est défini comme exécutable avec chmod +x ./myscript.py
Python peut également avoir des expressions régulières, notamment le module re
, qui possède la fonction re.sub()
, qui peut être utilisée pour des remplacements plus avancés.
sed
est la chaîne s ed , en ce sens que vous pouvez utiliser |
(pipe) pour envoyer des flux standard (STDIN et STDOUT spécifiquement) via sed
et les modifier par programmation à la volée, ce qui en fait un outil pratique dans Unix tradition philosophique; mais peut aussi éditer directement des fichiers, en utilisant le paramètre -i
mentionné ci-dessous.
Considérez ce qui suit :
sed -i -e 's/few/asd/g' hello.txt
s/
est utilisé pour s ubstitute l'expression trouvée few
avec asd
name__:
Les rares, les courageux.
Les asd, les braves.
/g
signifie "global", ce qui signifie le faire pour toute la ligne. Si vous laissez le /g
(avec s/few/asd/
, il doit toujours y avoir trois barres obliques quoi qu'il en soit) et que few
apparaisse deux fois sur la même ligne, seul le premier few
est remplacé par asd
name__:
Les rares hommes, les rares femmes, les braves.
Les hommes, les rares femmes, les braves.
Ceci est utile dans certaines circonstances, comme modifier des caractères spéciaux au début des lignes (par exemple, remplacer les symboles plus grands que certaines personnes utilisent pour citer le contenu précédent dans les fils de courrier électronique avec un onglet horizontal tout en laissant une inégalité algébrique citée plus tard dans la ligne. inaltéré), mais dans votre exemple où vous spécifiez que n'importe où few
doit être remplacé, assurez-vous que vous avez bien ce /g
.
Les deux options suivantes (drapeaux) sont combinées en une seule, -ie
:
L'option -i
permet d'éditer i n place sur le fichier hello.txt
.
L'option -e
indique que la commande e est exécutée, dans ce cas, s/
.
Remarque: Il est important que vous utilisiez -i -e
pour rechercher/remplacer. Si vous faites -ie
, vous créez une sauvegarde de chaque fichier avec la lettre 'e' ajoutée.
Vous pouvez faire comme ça:
locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g"
Exemples: pour remplacer toutes les occurrences [logdir ',' '] (sans []) par [logdir', os.getcwd ()] dans tous les fichiers résultant de la commande de localisation, faites:
ex1:
locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"
ex2:
locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"
où [tensorboard/program.py] est le fichier à rechercher