Pregunta

Tengo un archivo que contiene este tipo de rutas:

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

Y me gustaría obtener el siguiente archivo:

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

Tenga en cuenta que la ruta no coincidente no debe modificarse.

Sé cómo hacer esto con sed para un número fijo de subdirecciones, pero un número variable me está dando problemas. En realidad, tendría que usar muchas expresiones s/x/y/ (tantas como la profundidad máxima ... no muy elegante).

Puede estar con awk, pero este tipo de magia está más allá de mis habilidades.

Para su información, necesito este truco para corregir algunos archivos binarios gcov en una plataforma cygwin.


Estoy tratando con archivos binarios; por lo tanto, podría tener el siguiente tipo de datos:

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

que debe traducirse como:

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

El primer \ no debe traducirse, a pesar de que está en la misma línea.

Sin embargo, acabo de revisar mis .gcno archivos mientras edito este texto y parece que todas las rutas están flanqueadas con ceros, por lo que la mayoría de las respuestas a continuación deberían encajar.

¿Fue útil?

Solución

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

Otros consejos

Recomiendo que busque en la utilidad cygpath, que convierte los nombres de ruta de un formato a otro. Por ejemplo en mi máquina:

$ cygpath `pwd`
/home/jericson

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

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

Aquí hay una implementación de Perl de lo que solicitó:

$ 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

Funciona directamente con la cadena, por lo que funcionará en cualquier lugar. Puede combinarlo con C:goodfoo.c, pero solo funciona en máquinas que tienen esa ruta:

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

(Como no tengo C: \ good en mi máquina, obtengo resultados como <=>. Si usa una ruta real en su máquina, debería funcionar correctamente).

Desea sustituir '/' por todo '\' pero solo en las líneas que coinciden con la ruta correcta del directorio. Tanto sed como awk le permitirán hacer esto al tener una expresión LHS (coincidencia) que solo selecciona las líneas con la ruta correcta.

Un script sed trivial para hacer esto se vería así:

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

Para un archivo:

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

Obtendrá el resultado a continuación:

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

Así es como lo haría en awk:

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

Luego ejecútelo usando el comando:

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

O con un poco de ayuda del buen viejo 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

prueba esto

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

o esto

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top