Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
I have a file in this pattern
124334 2323 c:\program files\somefile 124334 2323 c:\program files\somepath\somefile 124334 2323 c:\program files\with space/somefile 124334 2323 c:\program files\with space/with another space/somefile .... .. .. ...
What i want to do is convert all spaces in the names which lies within / and /, / and \, \ and \ to underscores(_) to all the lines in the file. Each column is seperated by spaces, so i don't want them to be disturbed. So my file would look like
124334 2323 c:\program_files\somefile 124334 2323 c:\program_files\somepath\somefile 124334 2323 c:\program_files\with_space/somefile 124334 2323 c:\program_files\with_space/with_another_space/somefile
Thanks!

Replies are listed 'Best First'.
Re: File regex question
by BrowserUk (Patriarch) on Sep 16, 2003 at 07:28 UTC

    Try this

    perl -pe"s[ (?<=\\|/) (.*?) (?=\\|/) ][ (my$x=$1) =~ s{ }{_}g; $x]gex" + file

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

      Thanks!
      I would appreciate if you could tell me how to implement the same in a program? I would start with open FH, "<file";
        I would start with open FH, "<file";

        No, you should not. You should always test the return value of open. Furthermore, I wouldn't use second class variables if I can avoid it. Finally, you may prefer 3-arg open over magic 2-arg open:

        open my $fh, "<", "file" or die "Failed to open 'file': $!";

        Abigail

        Something like this (untested) code may be what your looking for.

        #! perl -w use strict; open IN, '<', 'file' or die $!; open OUT, '>', 'temp' or die $!; while( <IN> ) { s[ (?<=\\|/) (.*?) (?=\\|/) ][ (my$x=$1) =~ s{ }{_}g; $x ]gex; print OUT; } close IN; close OUT; rename 'file', 'file.bak'; rename 'temp', 'file';

        You could also look at using $INPLACE_EDIT ($^I) to have perl do the backup and rename for you.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
        If I understand your problem, I can solve it! Of course, the same can be said for you.

Re: File regex question
by pzbagel (Chaplain) on Sep 16, 2003 at 07:32 UTC

    I believe this code will work. I assume that the filename is the last thing on the line so I split on the :/ after the drive letter (notice it handles both types of slashes) and then it substitutes spaces anywhere after that in the string:

    #!/usr/bin/perl -w use strict; + while(<DATA>) { my @line=split /(:[\\\/])/; $line[2]=~s/ /_/g; print join "", @line; } __DATA__ 124334 2323 c:\program files\somefile 124334 2323 c:\program files\somepath\somefile 124334 2323 c:\program files\with space/somefile 124334 2323 c:\program files\with space/with another space/somefile

    HTH

Re: File regex question
by gjb (Vicar) on Sep 16, 2003 at 07:36 UTC

    Just for the fun of it, here's an approach using lvalues:

    substr($line, 12) =~ s/ /_/g;
    It substitutes the replacement into the relevant part of the string.

    Hope this helps, -gjb-

Re: File regex question
by delirium (Chaplain) on Sep 16, 2003 at 11:59 UTC
    Why is it that you're doing this? Are you going to take that file and pull it into a spreadsheet? Are you actually planning on renaming your files and directories to have underscores in them?

    If you're passing this data to another application that will choke on the spaces, you may want to check and see if quoting the directory/file names will work. Then you could do something like....

    perl -i.bak -lne '@F=split(/ /,$_,3);print "$F[0] $F[1] \"$F[2]\""' filename

    Of course, that doesn't take into account any lines not matching the expected format (e.g., blank lines are no longer blank)