web-dev-qa-db-fra.com

changer de ficelle avec sed, où est-il allé?

$ cat test-paths.txt 
test/sub2/configuration.php
test/sub3/configuration.php
test/configuration.php
test/sub1/configuration.php

$ cat find-Host-test 
#!/bin/bash
for i in `cat test-paths.txt`
 do 
  echo $i
  grep "public \$Host = '127.0.0.1';" $i
  #echo $?
  if [ $? -eq 0 ]
   then
    echo "there's config file"
    sed $i 's/$Host = 127.0.0.1/$Host = localhost/' 
    echo "changed to"
    grep "public \$Host =" $i
  fi
 done

l'exécution de find-Host-test a pour résultat

$ bash find-Host-test 
test/sub2/configuration.php
    public $Host = '127.0.0.1';
there's config file
sed: can't find label for jump to `est/sub2/configuration.php'
changed to
    public $Host = '127.0.0.1';
test/sub3/configuration.php
test/configuration.php
    public $Host = '127.0.0.1';
there's config file
sed: can't find label for jump to `est/configuration.php'
changed to
    public $Host = '127.0.0.1';
test/sub1/configuration.php
    public $Host = '127.0.0.1';
there's config file
sed: can't find label for jump to `est/sub1/configuration.php'
changed to
    public $Host = '127.0.0.1';

Pourquoi la disparition de "t" du dossier de test?

3
grepmaster

Votre invocation sed est fausse.

sed 's/$Host = 127.0.0.1/$Host = localhost/' "$i"

Voir la page de manuel de sed:

sed [OPTION]... {script-only-if-no-other-script} [input-file]

Le fichier d'entrée est le dernier argument, pas le premier.

Note importante: t dans sed est appelé une étiquette. Après t, le nom de l'étiquette suit. Dans votre cas, c'est le nom du fichier d'entrée sans le t initial. sed essaie donc de passer à une étiquette appelée est/sub2/configuration.php, que sed ne peut trouver nulle part. La deuxième expression s///g n'est jamais exécutée.

4
chaos

La bonne réponse du chaos a déjà donné la raison pour laquelle votre sed ne fonctionne pas.

Laissez-moi aller un peu plus loin pour indiquer une autre façon de parcourir votre fichier, puisque vous utilisez des étapes inutiles:

while IFS= read -r file
do
    echo "$file"
    if grep -q "public \$Host = '127.0.0.1';" "$file"; then
        echo "there's config file"
        sed 's/$Host = 127.0.0.1/$Host = localhost/' "$file"
        echo "changed to"
        grep "public \$Host =" "$file"
    fi
done < "test-paths.txt"

Différences:

  • Vous utilisez for i in $(cat test-paths.txt) (enfin, avec des backticks, mais je ne sais pas comment les citer). C'est bon, mais il vaut mieux utiliser une belle boucle while en faisant while read line; do ... done < file. De cette façon, vous lisez une ligne à la fois. Voir une discussion plus large sur le sujet dans Pour lire des lignes plutôt que des mots, dirigez/redirigez vers une boucle 'en lecture'.

  • De plus, utiliser des backticks est déconseillé. Il est préférable d'utiliser $(), car il est possible de les imbriquer. (En fait, nous avons déjà observé que c'était même mauvais en postant une réponse ici :))

  • Il n'est pas nécessaire de grep "something" puis de vérifier l'état $?. Vous pouvez directement utiliser grep -q pour cela.

  • Certaines de ces suggestions peuvent également être trouvées en collant votre script dans http://www.shellcheck.net/ .

1
fedorqui