Pergunta

Eu tenho um arquivo que contém esse tipo de caminhos:

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

E eu gostaria de obter o arquivo seguinte:

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

Note que o caminho não correspondência não deve ser modificado.

Eu sei como fazer isso com sed para um número fixo de subdir, mas um número variável está me dando problemas. Na verdade, eu teria que usar muitas expressões s/x/y/ (como muitos como a profundidade máxima ... não muito elegante).

Pode ser com awk, mas este tipo de magia está além de minhas habilidades.

FYI, eu preciso este truque para corrigir alguns arquivos gcov binários em uma plataforma cygwin.


Estou lidando com arquivos binários; portanto, eu poderia ter o seguinte tipo de dados:

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

que deve ser traduzido como:

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

O primeiro \ não deve ser traduzido, apesar de que é na mesma linha.

No entanto, eu verifiquei apenas meus arquivos .gcno durante a edição deste texto e parece que todos os caminhos são acompanhadas com zeros, então a maioria das respostas abaixo devem se encaixar.

Foi útil?

Solução

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

Outras dicas

Eu recomendo que você olhar para o utilitário cygpath, que converte nomes de caminho de um formato para outro. Por exemplo na minha máquina:

$ cygpath `pwd`
/home/jericson

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

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

Aqui está uma implementação Perl do que você pediu:

$ 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

Ele trabalha diretamente com a corda, por isso vai trabalhar em qualquer lugar. Você pode combiná-lo com cygpath, mas ele só funciona em máquinas que têm esse caminho:

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

(Desde que eu não tenho C:.. \ Boa na minha máquina, eu recebo uma saída como C:goodfoo.c Se você usar um caminho real na sua máquina, ele deve funcionar corretamente)

Você deseja substituir '/' para todos '\', mas apenas nas linhas que correspondem ao caminho do diretório bom. Ambos sed e awk vai deixar você fazer isso por ter uma expressão (correspondência) LHS que só pega as linhas com o caminho certo.

Um trivial sed script para fazer isso seria algo como:

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

Para um arquivo:

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

Você vai obter o resultado abaixo:

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

Aqui está como eu faria isso em awk:

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

Em seguida, executá-lo usando o comando:

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

Ou com alguma ajuda de boa ol' 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

Tente este

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

ou este

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top