tags:

views:

66

answers:

4

I have this line

/Od /D "WIN32" /D "_DEBUG" /FD /EHa /MDd /Fo"Debug" /Fd"Debug\vc80.pdb" /W3 /c /Zi /clr /TP .\main.cpp"

And I want to extract the .\main.cpp. I thought the following would do the trick:

if($string =~ /.*\s+(.*)$/i) {
 print "matched ",$1,"\n";
}

because this same regex works in Ruby, and extracts the string I required. How can I get it working?

EDIT: here's how I setup my string:

for(find_indexes(\@lines,"/MDd")) {
    my $actual_line = $lines[$_];
    $actual_line    = modify($actual_line,$additional_defs);
}

find_indexes returns the indexes of lines matching any of the parameter following the array ref. The modify sub will return a modified version of the string sent to it, containing some additional defines.

EDIT2: here's the modify sub:

sub modify {
    my $string      = shift;
    chomp($string);
    my @defines     = @_;
    if($string =~ /.*\s+(\".*?)$/) {
        my $match = $1;
        print "match is $match";
        my $string_copy = $string;
        print "|$string_copy|\n";
    }
}

The sub isn't complete, as I wasn't able to get it to work the way it should. I added an extra quote in the capturing group to force it to match the name. Something strange's happening though, I would expect the print of the $string_copy to print the original string surrounded in |. However, I only get the leading pipe, not the ending one. I thought maybe Perl is interpreting the interpolated variable wrong, and I tried to do it like this:

print "|",$string_copy,"|\n";

but I still only get a leading pipe. This leads me to think something may indeed be wrong with the string. I can't think of anything else.

+2  A: 
my $string = '/Od /D "WIN32" /D "_DEBUG" /FD /EHa /MDd /Fo"Debug" /Fd"Debug\vc80.pdb" /W3 /c /Zi /clr /TP .\main.cpp"';
if($string =~ /.*\s+(.*)$/i) {
    print "matched ",$1,"\n";
}

This works for me and prints matched .\main.cpp".

Please show how do you set up $string. It's possible that you somehow messed up with quotes or something.

EDIT: Is it possible that you have \x0d symbol at the end of your string? You would not notice it in log when you print your string and chomp won't remove it:

my $string = '/Od /D "WIN32" /D "_DEBUG" /FD /EHa /MDd /Fo"Debug" /Fd"Debug\vc80.pdb" /W3 /c /Zi /clr /TP .\main.cpp"' . "\x0d";
chomp $string;
if($string =~ /.*\s+(.*)$/i) {
    print "matched ",$1,"\n";
}

This prints matched for me, without capturing the file name. Maybe that's your case?

C:\>perl --version

This is perl, v5.10.1 built for MSWin32-x64-multi-thread
Paul
I've now posted almost all the code. Any ideas?
Geo
OP said that hes piping the string in from a file. I'm able to reproduce his problem now.
gnucom
@gnucom, I'm only displaying some pipes, as in |var| so that I can see if the string has extra characters :)
Geo
That's just the case. For example, if file is written with Windows line endings (`\x0d\x0a`) and there is Cygwin Perl that thinks that line ending is `\x0a` there will be `\x0d` at the end of the string and regexp won't match.
Paul
The version is `This is perl, v5.10.1 built for MSWin32-x86-multi-thread`. How does `\x0d` affect the string?
Geo
Possibly `\x0d` at the end of the string is not matched neither by `.` not by `$`.
Paul
How can I fix the string?
Geo
You can try this: `$string =~ s/[\x0a\x0d]//g;`
Paul
Thank you very much! I would never would have thought that the newline difference was causing this.
Geo
You could also try adding this before your chomp: `local $/ = "\r\n";`
pioto
A: 

Try this:

#!/usr/bin/perl

$string = <STDIN>;
chomp($string);
print $string;

if($string =~ /.*\s+(.*)$/) {
  print "\nmatched ",$1,"\n";
}

This is perl, v5.8.8 built for i486-linux-gnu-thread-multi

gnucom
It does not match the string. I get the same output.
Geo
It must be how you're passing in your string then. Can you show us the exact command you're using?
gnucom
I'm reading the string from a file. It should be auto-escaped, right?
Geo
Okay, this version is working for me now.
gnucom
+2  A: 

The leading .* is meaningless, as is the /i modifier.

If the string ends in a newline, that will be matched by the \s+. Since the (.*) that follows can match nothing, the match will succeed but $1 will be empty. Instead, force it to match something: /(\S+)"$/

Michael Carman
The string is chomped before I try to match against it.
Geo
+1  A: 

It looks like all you actually want is

$string =~ /(\S+)$/
hobbs
heh, yah, thats cleaner.
gnucom