Sostituzione del percorso da DOS a UNIX all'interno di un file
Domanda
Ho un file che contiene questo tipo di percorsi:
C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c
E vorrei ottenere il seguente file:
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c
Nota che il percorso non corrispondente non deve essere modificato.
So come farlo con sed per un numero fisso di sottodir, ma un numero variabile mi dà problemi. In realtà, dovrei usare molte s/x/y/
espressioni (fino alla profondità massima ... non molto elegante).
Può essere con awk, ma questo tipo di magia va oltre le mie capacità.
Cordiali saluti, ho bisogno di questo trucco per correggere alcuni file binari di gcov su una piattaforma cygwin.
Mi occupo di file binari; pertanto, potrei avere il seguente tipo di dati:
bindata\bindata%bindataC:\good\foo.c
che dovrebbe essere tradotto come:
bindata\bindata%bindataC:/good/foo.c
Il primo \
non deve essere tradotto, nonostante sia sulla stessa riga.
Tuttavia, ho appena controllato i miei .gcno
file durante la modifica di questo testo e sembra che tutti i percorsi siano fiancheggiati da zeri, quindi la maggior parte delle risposte qui sotto dovrebbero adattarsi.
Soluzione
sed -e '/^C:\\good/ s/\\/\//g' input_file.txt
Altri suggerimenti
Ti consiglio di consultare l'utilità cygpath
, che converte i nomi dei percorsi da un formato all'altro. Ad esempio sul mio computer:
$ cygpath `pwd`
/home/jericson
$ cygpath -w `pwd`
D:\root\home\jericson
$ cygpath -m `pwd`
D:/root/home/jericson
Ecco un'implementazione Perl di ciò che hai chiesto:
$ 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
Funziona direttamente con la stringa, quindi funzionerà ovunque. Puoi combinarlo con C:goodfoo.c
, ma funziona solo su macchine che hanno quel percorso:
perl -pe '$_ = `cygpath -m $_` if /good/'
(Dato che non ho C: \ good sulla mia macchina, ottengo un output come <=>. Se usi un percorso reale sulla tua macchina, dovrebbe funzionare correttamente.)
Si desidera sostituire '/
' con tutti '\
' ma solo sulle righe che corrispondono al percorso della directory valido. Sia sed che awk ti permetteranno di farlo avendo un'espressione LHS (matching) che seleziona solo le linee con il percorso giusto.
Un banale script sed per fare questo sarebbe simile:
/[Cc]:\\good/ s/\\/\//g
Per un file:
c:\bad\foo
c:\bad\foo\bar
c:\good\foo
c:\good\foo\bar
Otterrai l'output di seguito:
c:\bad\foo
c:\bad\foo\bar
c:/good/foo
c:/good/foo/bar
Ecco come lo farei in awk:
# fixpaths.awk
/C:\\good/ {
gsub(/\\/,"/",$1);
print $1 >> outfile;
}
Quindi eseguilo usando il comando:
awk -f fixpaths.awk paths.txt; mv outfile paths.txt
O con l'aiuto del buon vecchio 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
prova questo
sed -re '/\\good\\/ s/\\/\//g' temp.txt
o questo
awk -F"\\" '{if($2=="good"){OFS="\/"; $1=$1;} print $0}' temp.txt