2009-08-20 8 views
1

Mise à jour:Comment canaliser les chemins de fichiers Windows dans Perl?

Je peux faire un problème plus simple à résoudre:

Je veux savoir ce que l'expression régulière correcte serait de substituer une seule occurrence d'une barre oblique inverse avec deux barres obliques arrière.

Je veux tourner ceci:

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

dans:

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

question d'origine:

Je souhaite modifier ce qui suit dans un fichier en utilisant un Perl Regex:

  • toutes les occurrences d'une seule barre oblique inverse à deux barres obliques
  • toutes les occurrences d'une barre oblique à dos deux barres obliques

J'ai essayé les éléments suivants:

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

où% VIDEOLOG_PROPERTIES_FILE% contient:

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

... Qu'est-il arrivé? – chaos

+0

ne savez pas comment MSWindows gère ces choses, mais vous pouvez essayer échapper à toutes vos antislashs une fois de plus s # \\\\ # \\\\\\\\ # g – Inshallah

+0

« ... et ce qui est arrivé - le chaos » . oui, c'est ce que fait Perl. (Je plaisante j'aime Perl ;-)) – p4bl0

Répondre

6

Pour REPLACE de base:

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

Pour remplacer les barres obliques seulement et anti-slash qui ne semblent pas adjacents à une autre instance du même caractère:

perl -p -i.orig -e "s#(?<!/)/(?!/)#\\\\#g; s#(?<\\)\\(?!\\)#\\\\#g" %VIDEOLOG_PROPERTIES_FILE% 
+0

Pouvez-vous expliquer pourquoi cela fonctionnerait différemment de ce que Faust a déjà essayé? –

+1

@Rob: bien, pour commencer, ça ne produit pas d'erreur de syntaxe. Comme Eevee le dit dans sa réponse, vous pouvez corriger cela en ajoutant un point-virgule à la première substitution. Chaos rend les deux regex plus simples en les combinant dans la classe de personnage. – Telemachus

+0

Lorsque j'utilise ce que vous avez suggéré, j'obtiens: vlc.plugin.path = C: \\ Program Files \\ JekyllV0.9.2 \\\\ VLC_1.0.0 \\\\ plugins Y a-t-il un moyen d'éviter de changer le existant "\\" à "\\\\"? –

3

Je suis assez sûr que Perl concaténer aveuglément tous ses -e arguments, si ceux-ci sont écrasements en s#\\#\\\\#gs#/#\\\\#g, puis la deuxième regex ressemble à un commentaire. Il fonctionne pour moi si je le change en -e 's#\\#\\\\#g; s#/#\\\\#g'.

Bien sûr, vous pouvez le faire avec une seule regex, puisque vous utilisez le même remplacement deux fois.

0
[21:09:00][[email protected]:~]$ perl -pe 's#\/#\/\/#g; s#\\#\\\\#g' test.txt 
vlc.plugin.path = C:\\Program Files\\JekyllV0.9.2//VLC_1.0.0//plugins 
3

Il ne fonctionne pas, parce que Perl ne gère pas deux drapeaux -e - sans virgule « entre » les deux commandes. Vous devez écrire comme ci-dessous (si vous perdez le d-citation juste après « perl », c'est.)

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

je fais quelque chose de similaire, mais parce que Perl prend en charge '/' sur le PC, ma préférence est pour barres obliquesDonc j'utilise les éléments suivants:

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

Ainsi, il peut être facilement retourné à

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

Maintenant un mot sur la raison pour laquelle je fais ça: parfois, les gens ne peux pas comprendre si oui ou non ils devraient mettre une barre oblique au début ou à la fin de parties de chemins qui seront concaténées. Parfois, vous vous retrouvez avec même deux barres obliques. (Mais pas si vous utilisez File::Spec.) Ainsi, il est bon de gérer ce genre de collisions. Surtout parce que ça va être un chemin, nous voulons prendre cependant beaucoup de slashs de n'importe quel genre et les transformer en ceux que nous aimons.

De plus, je fais même ceci:

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

Parce qu'il capture les cas où il est le même groupe de barres obliques séparés par un point qui ne fait rien, parce que la voie sage / < =>(/+.)+ pour les programmes et les scripts qui gèrent les points dans les noms de chemin, tandis que les autres programmes vont faire une erreur.

+0

Ce n'est pas vraiment vrai. Perl gère deux clauses '-e' très bien; ce qu'il ne fait pas est d'insérer un point-virgule implicite entre eux. – chaos

+0

@chaos Vous êtes * absolument * droite, me couleur surpris que je dois dire Perl pour y mettre un séparateur de commande. Je suis toujours parti avec l'hypothèse fonctionnelle que cela ne fonctionne pas.Mais j'ai essayé et ça a marché sur toutes les plateformes que j'ai essayées. Merci! – Axeman

4

Vous voulez File::Spec->canonpath.

Mise à jour :: En fait, c'était la mauvaise recommandation. Cela fonctionnera pour les appels de fonction internes, etc. mais il écrira des barres obliques inverses simples dans le fichier. Cependant, ce qui suit fonctionnera mieux:

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

Sortie:

 
C:\\Program Files\\JekyllV0.9.2\\VLC_1.0.0\\plugins 
C:\\Program Files\\JekyllV0.9.2\\VLC_1.0.0\\plugins 
+0

Merci. C'était très instructif et utile. –

Questions connexes