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.

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top