837 votes

Rechercher et remplacer à l'intérieur d'un fichier texte à partir d'une commande Bash

Quelle est la façon la plus simple de faire un rechercher et remplacer pour une chaîne d'entrée, dire abc, et de la remplacer par une autre chaîne, dire XYZ fichier /tmp/file.txt?

J'écris une application et à l'aide de IronPython pour exécuter des commandes via SSH, mais je ne sais pas Unix que bien et ne sais pas quoi chercher.

J'ai entendu dire que Bash, en plus d'être une interface de ligne de commande, peut être un puissant langage de script. Donc, si c'est vrai, je suppose que vous pouvez effectuer des actions comme celles-ci.

Puis-je le faire avec bash, et ce qui est le plus simple (une seule ligne de script pour atteindre mon objectif?

1350voto

johnny Points 1812

Le plus simple est d'utiliser sed (ou perl):

sed -i -e 's/abc/XYZ/g' /tmp/file.txt

Qui invoquera sed pour effectuer une modification sur place en raison de l'option -i . Cela peut être appelé depuis bash.

Si vous voulez vraiment utiliser simplement bash, alors ce qui suit peut fonctionner:

while read a ; do echo ${a//abc/XYZ} ; done < /tmp/file.txt > /tmp/file.txt.t ; mv /tmp/file.txt{.t,}

Cela boucle sur chaque ligne, en effectuant une substitution et en écrivant dans un fichier temporaire (ne pas vouloir écraser l'entrée). Le mouvement à la fin se déplace simplement vers le nom d'origine.

184voto

Alnitak Points 143355

La manipulation des fichiers n'est normalement pas effectuée par Bash, mais par les programmes invoqués par Bash, par exemple:

 > perl -pi -e 's/abc/XYZ/g' /tmp/file.txt
 

L'indicateur -i dit de faire un remplacement sur place.

Voir man perlrun pour plus de détails, y compris comment faire une sauvegarde du fichier original.

76voto

rayro Points 111

J'ai été surpris parce que je suis tombé sur ça ...

Il y a une commande "replace" qui est fournie avec le paquet "mysql-server" , donc si vous l'avez installé, essayez-le:

 # replace string abc to XYZ in files
replace "abc" "XYZ" -- file.txt file2.txt file3.txt

# or pipe an echo to replace
echo "abcdef" |replace "abc" "XYZ"
 

Voyez l' homme remplacer pour plus sur ceci ...

51voto

slim Points 12620

Bash, comme d'autres coquilles, n'est qu'un outil pour la coordination des autres commandes. En général, vous essayez d'utiliser les commandes UNIX standard, mais vous pouvez bien sûr utiliser Bash pour invoquer quoi que ce soit, y compris vos propres programmes compilés, d'autres scripts shell, Python et Perl, scripts etc.

Dans ce cas, il ya un couple de façons de le faire.

Si vous voulez lire un fichier, et l'écrire dans un autre fichier, recherche/remplacer comme vous allez, utiliser sed:

sed 's/abc/XYZ/g' <infile >outfile

Si vous souhaitez modifier le fichier en place (comme si l'ouverture du fichier dans un éditeur de texte, de le modifier, puis de le sauvegarder) fournir des instructions de l'éditeur de ligne de 'ex'

echo "%s/abc/XYZ/g
w
q
" | ex file

Ex, c'est comme vi sans le mode plein écran. Vous pouvez lui donner les mêmes commandes que vous au vi ':' invite.

37voto

centurian Points 131

Trouvé ce fil parmi d'autres, et je suis d'accord qu'il contient la plus complète de réponses donc j'ajoute la mienne aussi:

1) sed et ed sont donc useful...by main!!! Regardez ce code à partir de @Johnny:

sed -i -e 's/abc/XYZ/g' /tmp/file.txt

2) quand mon restriction est de l'utiliser dans un script shell, alors, aucune variable ne peut être utilisé à l'intérieur à la place de l'abc ou XYZ! Cela semble d'accord avec ce que je comprends au moins. Donc, je ne peux pas utiliser:

x='abc'
y='XYZ'
sed -i -e 's/$x/$y/g' /tmp/file.txt
#or,
sed -i -e "s/$x/$y/g" /tmp/file.txt

mais, que pouvons-nous faire? Comme, @Johnny, a déclaré l'utilisation d'un tout lu...", mais, malheureusement, ce n'est pas la fin de l'histoire. La suite a bien fonctionné avec moi:

#edit user's virtual domain
result=
#if nullglob is set then, unset it temporarily
is_nullglob=$( shopt -s | egrep -i '*nullglob' )
if [[ is_nullglob ]]; then
   shopt -u nullglob
fi
while IFS= read -r line; do
   line="${line//'<servername>'/$server}"
   line="${line//'<serveralias>'/$alias}"
   line="${line//'<user>'/$user}"
   line="${line//'<group>'/$group}"
   result="$result""$line"'\n'
done < $tmp
echo -e $result > $tmp
#if nullglob was set then, re-enable it
if [[ is_nullglob ]]; then
   shopt -s nullglob
fi
#move user's virtual domain to Apache 2 domain directory
......

3) Comme on peut le voir si nullglob est définie, alors, il se comporte étrangement quand il y a une chaîne de caractères contenant un * comme dans

<VirtualHost *:80>
 ServerName www.example.com

qui devient

<VirtualHost ServerName www.example.com

il n'y a pas de fin, équerre de fixation et Apache2 peut pas charger même!

4) Ce type d'analyse devrait être plus lente que d'un coup de recherche et de remplacement, mais, comme vous avez déjà vu, il y a 4 variables pour 4 différents modèles de recherche de travail de l'un seulement d'analyser le cycle de!

La solution la plus adaptée je pense, avec les hypothèses du problème.

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