DOS para substituição de caminho UNIX dentro de um arquivo
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.
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