Question

J'ai un fichier qui contient ce type de chemins:

C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c

Et j'aimerais obtenir le fichier suivant:

C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c

Notez que le chemin qui ne correspond pas ne doit pas être modifié.

Je sais comment faire cela avec sed pour un nombre fixe de sous-répertoires, mais un nombre variable me pose problème. En fait, je devrais utiliser de nombreuses s/x/y/ expressions (autant que la profondeur maximale ... pas très élégante).

Peut-être avec awk, mais ce genre de magie dépasse mes compétences.

Pour info, j'ai besoin de cette astuce pour corriger certains fichiers binaires gcov sur une plateforme cygwin.

Je traite de fichiers binaires; par conséquent, je pourrais avoir le type de données suivant:

bindata\bindata%bindataC:\good\foo.c

qui devrait être traduit par:

bindata\bindata%bindataC:/good/foo.c

Le premier \ ne doit pas être traduit, même s'il se trouve sur la même ligne.

Cependant, je viens de vérifier mes .gcno fichiers lors de la modification de ce texte. Il semble que tous les chemins soient flanqués de zéros. La plupart des réponses ci-dessous doivent donc correspondre.

Était-ce utile?

La solution

sed -e '/^C:\\good/ s/\\/\//g' input_file.txt

Autres conseils

Je vous conseillerais de consulter l'utilitaire cygpath, qui convertit les noms de chemins d'un format à un autre. Par exemple sur ma machine:

$ cygpath `pwd`
/home/jericson

$ cygpath -w `pwd`
D:\root\home\jericson

$ cygpath -m `pwd`
D:/root/home/jericson

Voici une implémentation Perl de ce que vous avez demandé:

$ echo 'C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c' | perl -pe 's|\\|/|g if /good/'
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c

Cela fonctionne directement avec la chaîne, donc cela fonctionnera n'importe où. Vous pouvez le combiner avec C:goodfoo.c, mais cela ne fonctionne que sur les machines ayant ce chemin:

perl -pe '$_ = `cygpath -m $_` if /good/'

(Comme je n’ai pas bien C: \ bien sur ma machine, j’obtiens une sortie du type <=>. Si vous utilisez un chemin réel sur votre machine, cela devrait fonctionner correctement.)

Vous souhaitez remplacer "/" par "\" mais uniquement sur les lignes correspondant au bon chemin de répertoire. Sed et awk vous permettront de le faire en utilisant une expression LHS (correspondante) qui ne sélectionne que les lignes avec le bon chemin.

Un script sed trivial pour cela ressemblerait à ceci:

/[Cc]:\\good/ s/\\/\//g

Pour un fichier:

c:\bad\foo
c:\bad\foo\bar
c:\good\foo
c:\good\foo\bar

Vous obtiendrez le résultat ci-dessous:

c:\bad\foo
c:\bad\foo\bar
c:/good/foo
c:/good/foo/bar

Voici comment je le ferais dans awk:

# fixpaths.awk
/C:\\good/ {
   gsub(/\\/,"/",$1);
   print $1 >> outfile;
}

Exécutez-le ensuite à l'aide de la commande suivante:

awk -f fixpaths.awk paths.txt; mv outfile paths.txt

Ou avec l'aide du bon vieux Bash:

#!/bin/bash

cat file | while read LINE
do
        if <bad_condition>
        then
                echo "$LINE" >> newfile
        else
                echo "$LINE" | sed -e "s/\\/\//g" >> newfile
        fi
done

essayez ceci

sed -re '/\\good\\/ s/\\/\//g' temp.txt

ou ceci

awk -F"\\" '{if($2=="good"){OFS="\/"; $1=$1;} print $0}' temp.txt

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top