Как я могу канонизировать пути к файлам Windows в Perl? - PullRequest
1 голос
/ 20 августа 2009

Обновление:

Я могу сделать эту задачу проще для решения:

Я хочу выяснить, каким будет правильное регулярное выражение для замены любого единственного вхождения обратной косой черты двумя косыми чертами.

Я хочу включить это:

vlc.plugin.path = C:\Program Files\JekyllV0.9.2\\VLC_1.0.0\\plugins

в:

vlc.plugin.path = C:\\Program Files\\JekyllV0.9.2\\VLC_1.0.0\\plugins

Оригинальный вопрос:

Я хочу изменить следующее в файле, используя Perl Regex:

  • все вхождения одной косой черты в две косые черты
  • все вхождения одной прямой косой черты в две обратной косой черты

Я попробовал следующее:

perl" -p -i.orig -e "s#\\#\\\\#g" -e "s#/#\\\\#g" %VIDEOLOG_PROPERTIES_FILE%

, где% VIDEOLOG_PROPERTIES_FILE% содержит:

vlc.plugin.path = C:\Program Files\JekyllV0.9.2/VLC_1.0.0/plugins

Ответы [ 5 ]

6 голосов
/ 20 августа 2009

Для базовой замены:

perl -p -i.orig -e "s#[/\\]#\\\\#g" %VIDEOLOG_PROPERTIES_FILE%

Чтобы заменить только косые черты и обратную косую черту, которые не отображаются рядом с другим экземпляром того же символа:

perl -p -i.orig -e "s#(?<!/)/(?!/)#\\\\#g; s#(?<\\)\\(?!\\)#\\\\#g" %VIDEOLOG_PROPERTIES_FILE%
4 голосов
/ 21 августа 2009

Вы хотите File::Spec->canonpath.

Обновление :: На самом деле это была неправильная рекомендация. Это будет работать для внутренних вызовов функций и т. Д., Но оно будет записывать одиночные обратные слеши в файл. Тем не менее, следующее будет работать лучше:

#!/usr/bin/perl

use strict;
use warnings;

use Config::INI::Reader;

my $config = Config::INI::Reader->read_handle(\*DATA);

my $var1 = $config->{_}->{'vlc.plugin.path1'};
my $var2 = $config->{_}->{'vlc.plugin.path2'};

for my $v ($var1, $var2) {
    $v =~ s! (?: [\\]{1,2} ) | (?:/) !\\\\!gx;
    print "$v\n";
}

__DATA__
vlc.plugin.path1 = C:\Program Files\JekyllV0.9.2\\VLC_1.0.0\\plugins
vlc.plugin.path2 = C:\Program Files\JekyllV0.9.2/VLC_1.0.0/plugins

Выход:

C:\\Program Files\\JekyllV0.9.2\\VLC_1.0.0\\plugins
C:\\Program Files\\JekyllV0.9.2\\VLC_1.0.0\\plugins
3 голосов
/ 20 августа 2009

Это не работает, потому что perl не обрабатывает два флага -e - без точки с запятой "между" двумя командами. Вы должны написать это, как показано ниже (если вы потеряете d-кавычку сразу после 'perl', то есть.)

perl -p -i.orig -e "s#\\#\\\\#g;" -e "s#/#\\\\#g" %VIDEOLOG_PROPERTIES_FILE%

Я делаю нечто подобное, но поскольку Perl поддерживает '/' на ПК, я предпочитаю использовать косую черту. Поэтому я использую следующее:

s![\\/]+!/!g;

Таким образом, его можно легко повернуть к

s![\\/]+!\\\\!g;

Теперь несколько слов о том, почему я так поступаю: иногда люди не могут понять, стоит ли им ставить косую черту в начале или конце частей путей, которые будут объединены. Временами вы получаете даже двойные косые черты. (Но не в том случае, если вы используете File :: Spec .), Поэтому хорошо обрабатывать такие коллизии. Тем более, что это будет путь, мы хотим взять как можно больше слешей и превратить их в то, что нам нравится.

Кроме того, я даже делаю это:

s!([\\/]+([.][\\/]+)?)+!/!g

Поскольку он охватывает те случаи, когда это тот же кластер слешей, разделенных точкой, который ничего не делает, потому что по пути / <=> (/+.)+ для тех программ и сценариев, которые обрабатывают точки в именах путей, в то время другие программы будут выдавать ошибку.

3 голосов
/ 20 августа 2009

Я почти уверен, что Perl слепо объединяет все свои -e аргументы, поэтому они сводятся в s#\\#\\\\#gs#/#\\\\#g, а затем второе регулярное выражение выглядит как комментарий.

Это работает для меня, если я изменю его на -e 's#\\#\\\\#g; s#/#\\\\#g'.

Конечно, вы можете сделать это с помощью одного регулярного выражения, поскольку вы используете одну и ту же замену оба раза.

0 голосов
/ 20 августа 2009
[21:09:00][mgrad@zuza-3:~]$ perl -pe 's#\/#\/\/#g; s#\\#\\\\#g' test.txt
vlc.plugin.path = C:\\Program Files\\JekyllV0.9.2//VLC_1.0.0//plugins
...