Подстановка пути из DOS в UNIX в файле - PullRequest
4 голосов
/ 30 января 2009

У меня есть файл, который содержит такие пути:

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

И я хотел бы получить следующий файл:

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

Обратите внимание, что несоответствующий путь не должен изменяться.

Я знаю, как сделать это с помощью sed для фиксированного числа subdir, но переменное число доставляет мне проблемы. На самом деле, мне пришлось бы использовать много s/x/y/ выражений (столько, сколько максимальная глубина ... не очень элегантно).

Может быть с awk, но этот вид магии мне не под силу.

Кстати, мне нужен этот трюк, чтобы исправить некоторые двоичные файлы gcov на платформе cygwin.


Я имею дело с двоичными файлами; поэтому у меня могут быть следующие данные:

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

что должно быть переведено как:

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

Первый \ не должен переводиться, несмотря на то, что он находится на той же строке.

Однако я только что проверил мои .gcno файлы при редактировании этого текста, и похоже, что все пути обведены нулями, поэтому большинство ответов ниже должно соответствовать.

Ответы [ 6 ]

5 голосов
/ 30 января 2009
sed -e '/^C:\\good/ s/\\/\//g' input_file.txt
3 голосов
/ 30 января 2009

Я бы порекомендовал вам заглянуть в утилиту cygpath, которая преобразует имена путей из одного формата в другой. Например на моей машине:

$ cygpath `pwd`
/home/jericson

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

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

Вот реализация Perl того, что вы просили:

$ 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

Работает напрямую со строкой, поэтому будет работать где угодно. Вы можете объединить его с cygpath, но он работает только на машинах с таким путем:

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

(Поскольку у меня нет C: \ good на моей машине, я получаю вывод вроде C:goodfoo.c. Если вы используете реальный путь на вашей машине, он должен работать правильно.)

1 голос
/ 30 января 2009

Вот как я бы сделал это в awk:

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

Затем запустите его с помощью команды:

awk -f fixpaths.awk paths.txt; mv outfile paths.txt
1 голос
/ 30 января 2009

Вы хотите заменить '/' на все '\', но только в строках, которые соответствуют правильному пути к каталогу. И sed, и awk позволят вам сделать это с помощью выражения LHS (соответствия), которое выбирает только строки с правильным путем.

Тривиальный скрипт sed для этого будет выглядеть так:

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

Для файла:

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

Вы получите вывод ниже:

c:\bad\foo
c:\bad\foo\bar
c:/good/foo
c:/good/foo/bar
0 голосов
/ 21 января 2013

попробуйте

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

или это

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

0 голосов
/ 30 января 2009

Или с некоторой помощью доброго старина Баша:

#!/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
...