web-dev-qa-db-fra.com

Rechercher et remplacer la chaîne dans tous les fichiers récursifs à l'aide de grep et sed

Je reçois un

sed: -e expression #1, char 22: unterminated `s' command 

y a-t-il un problème sur mon script? Aussi le "oldstring" a des caractères spéciaux

#!bin/bash
oldstring='<script>"[oldscript]"</script>'
newstring='<script>"[newscript]"</script>'
grep -rl $oldstring /path/to/folder | xargs sed -i s/$oldstring/$newstring/g
31
jmazaredo

Comme @Didier l'a dit, vous pouvez changer votre délimiteur pour autre chose que /:

grep -rl $oldstring /path/to/folder | xargs sed -i s@$oldstring@$newstring@g
42
wudeng
grep -rl $oldstring . | xargs sed -i "s/$oldstring/$newstring/g"
13
Sreedhar GS

Les gars GNU) ont VRAIMENT foiré quand ils ont introduit la recherche récursive de fichiers dans grep. Grep sert à trouver des RE dans des fichiers et à imprimer la ligne correspondante (g/re/p, rappelez-vous?) PAS pour trouver des fichiers. Il existe un très bon outil avec un nom très évident pour les fichiers FINDing: que s’est-il passé pour le mantra UNIX de faire une chose et bien le faire?

Quoi qu'il en soit, voici comment vous feriez ce que vous voudriez en utilisant l'approche UNIX traditionnelle (non testée):

find /path/to/folder -type f -print |
while IFS= read -r file
do
   awk -v old="$oldstring" -v new="$newstring" '
      BEGIN{ rlength = length(old) }
      rstart = index($0,old) { $0 = substr($0,rstart-1) new substr($0,rstart+rlength) }
      { print }
   ' "$file" > tmp &&
   mv tmp "$file"
done

Ce n'est pas qu'en utilisant awk/index () au lieu de sed et grep, vous évitez la nécessité d'échapper à tous les métacaractères RE qui pourraient apparaître dans votre ancienne ou votre nouvelle chaîne, et de trouver un caractère à utiliser comme délimiteur sed '. n'apparaissent pas dans votre ancienne ou votre nouvelle chaîne, et vous n'avez pas besoin d'exécuter grep car le remplacement ne se produira que pour les fichiers contenant la chaîne souhaitée. Ceci dit, si vous ne voulez pas que l’horodatage du fichier change si vous ne le modifiez pas, faites simplement un diff sur tmp et le fichier original avant de faire le mv ou jetez un fgrep -q avant le awk.

Mise en garde: Ce qui précède ne fonctionnera pas pour les noms de fichiers contenant des nouvelles lignes. Si vous en avez, dites-le-nous et nous pourrons vous montrer comment les gérer.

5
Ed Morton

sed expression doit être citée

sed -i "s/$oldstring/$newstring/g"
4
Steven Penny