Comment trouver et remplacer des mots spécifiques dans un fichier texte en utilisant la ligne de commande ?
Comment incorporer les regex à ce système ?
Comment trouver et remplacer des mots spécifiques dans un fichier texte en utilisant la ligne de commande ?
sed -i 's/original/new/g' file.txt
Explication :
sed
= Stream EDitor-i
= sur place (c'est-à-dire sauvegarder dans le fichier d'origine)La chaîne de commande :
s
= la commande de substitutionoriginal
= une expression régulière décrivant le mot à remplacer (ou juste le mot lui-même)new
= le texte à remplacer parg
= global (c'est-à-dire remplacer toutes les occurrences et pas seulement la première)file.txt
= le nom du fichier
@Akiva Si vous incluez caractères spéciaux de regex dans votre recherche sed
leur correspondra. Ajoutez un -r
si vous souhaitez plutôt utiliser des RE étendus.
Puis-je utiliser la commande "sed -i" lorsque les chaînes "original" et "nouveau" contiennent des caractères spéciaux comme "/" ou similaires ?
Il y a une multitude de façons d'y parvenir. Selon la complexité de ce que l'on cherche à réaliser avec le remplacement de chaînes de caractères, et selon les outils avec lesquels l'utilisateur est familier, certaines méthodes peuvent être préférées à d'autres.
Dans cette réponse, j'utilise un simple 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 conçu pour le traitement de texte, mais des substitutions simples peuvent être effectuées via la fonction expansion des paramètres En particulier, nous pouvons utiliser ici 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 ne fait pas de remplacement en place, ce qui signifie que vous devriez enregistrer le nouveau texte dans un nouveau fichier, et vous débarrasser de l'ancien fichier, ou bien mv new.txt old.txt
Remarque : si vous êtes curieux de savoir pourquoi while IFS= read -r ; do ... done < input.txt
est utilisé, c'est en fait la façon dont Shell lit le fichier ligne par ligne. Voir ce pour référence.
AWK, étant un utilitaire de traitement de texte, est tout à fait approprié pour une telle tâche. Il peut effectuer des remplacements simples et des remplacements beaucoup plus avancés basés sur les principes suivants expressions régulières . Il assure deux fonctions : sub()
y gsub()
. La première remplace uniquement la première occurrence, tandis que la seconde remplace les occurrences de toute la chaîne. Par exemple, si nous avons la chaîne one potato two potato
le résultat serait le suivant :
$ 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, donc faire les mêmes choses avec input.txt
Ce serait facile :
awk '{sub(/blue/,"azure")}1' input.txt
En fonction de la version de AWK que vous avez, il se peut qu'il n'y ait pas d'édition en place, donc la pratique habituelle est d'enregistrer et de 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 les expressions régulières, mais pour de simples substitutions, il suffit de le faire :
sed 's/blue/azure/' input.txt
Ce qui est bien avec cet outil, c'est qu'il dispose d'une fonction d'édition sur place, que vous pouvez activer avec le bouton -i
drapeau.
Perl est un autre outil souvent utilisé pour le traitement de texte, mais c'est un langage à usage général, et il est utilisé dans les réseaux, l'administration système, les applications de bureau, et bien d'autres endroits. Il a emprunté beaucoup de concepts/caractéristiques à d'autres langages tels que C, sed, awk, et d'autres. Une simple substitution peut être effectuée comme suit :
perl -pe 's/blue/azure/' input.txt
Comme sed, perl possède également l'option -i.
Ce langage est très polyvalent et est également utilisé dans une grande variété d'applications. Il dispose d'un grand nombre de fonctions pour travailler avec des chaînes de caractères, notamment replace()
donc si vous avez une variable comme var="Hello World"
vous pourriez faire var.replace("Hello","Good Morning")
Une façon simple de lire un fichier et d'y remplacer une chaîne de caractères serait la suivante :
python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt
Avec Python, cependant, vous devez également sortir vers un nouveau fichier , ce que vous pouvez également faire à partir du lui-même. Par exemple, en voici un 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 l'argument de la ligne de commande serait la suivante
$ ./myscript.py input.txt
o
$ python ./myscript.py input.txt
Bien sûr, assurez-vous que ./myscript.py
se trouve 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 utiliser des expressions régulières, en particulier, il y a re
qui a re.sub()
qui peut être utilisée pour des remplacements plus avancés.
Belle compilation ! Un autre moyen possible, non mentionné ici, est d'utiliser la fonction tr
dans unix
Il existe un certain nombre de façons différentes de procéder. La première consiste à utiliser sed
et Regex. SED est un éditeur de flux qui permet de filtrer et de transformer du texte. Voici un exemple :
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 façon, qui peut être plus logique que < strin
y > strout
est avec des tuyaux !
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
Noter le cat
en cat file | sed '...'
n'est pas nécessaire. Vous pouvez dire directement sed '...' file
.
En effet, il est possible de réduire encore davantage cette situation : sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly
va prendre le fichier yarly et faire les 2 changements en place tout en faisant une sauvegarde. Utilisation de time bash -c "$COMMAND"
à la fois il suggère que cette version est un ~5 fois plus rapide.
Grâce à la commande gsub de l'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 faire un remplacement sur une colonne spécifique, alors faites comme ceci,
awk '{gsub(/pattern/,"replacement",column_number)}' file
Exemple :
awk '{gsub(/1/,"0",$1);}' file
Il remplace le 1 par le 0 sur la première colonne uniquement.
Par Perl,
$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.