Mam następujący plik wykonywalny .pl:
#!/usr/bin/env perl
$file = "TfbG_peaks.txt";
open(INFO, $file) or die("Could not open file.");
foreach $line (<INFO>) {
if ($line =~ m/[^_]*(?=_)/){
#print $line; #this prints lines, which means there are matches
print $1; #but this prints nothing
}
}
Na podstawie mojego czytania w http://goo.gl/YlEN7 i http://goo.gl/VlwKe, print $1;
powinien wydrukować pierwsze dopasowanie w każdym wierszu, ale tak nie jest.
Odpowiedzi:
2 dla odpowiedzi № 1Nie, $1
powinien wydrukować ciąg zapisany przez tzw przechwytywanie grup (stworzony przez konstrukcję bracketingu - ( ... )
). Na przykład:
if ($line =~ m/([^_]*)(?=_)/){
print $1;
# now this will print something,
# unless string begins from an underscore
# (which still matches the pattern, as * is read as "zero or more instances")
# are you sure you don"t need `+` here?
}
Wzór w oryginalnym kodzie nie zawierał żadnych grup przechwytywania, dlatego $1
był pusty (undef
, precyzyjnie) tam. I (?=...)
nie liczył się, ponieważ zostały one użyte do dodania podwyrażenia z wyprzedzeniem.
0 dla odpowiedzi nr 2
$1
drukuje, co pierwsze przechwycenie ((...)
) we wziętym wzorze.
Może myślałeś o tym
print $& if $line =~ /[^_]*(?=_)/; # BAD
lub
print ${^MATCH} if $line =~ /[^_]*(?=_)/p; # 5.10+
Ale poniższe byłyby prostsze (i działały przed 5.10):
print $1 if $line =~ /([^_]*)_/;
Uwaga: Otrzymasz zwiększenie wydajności, gdy wzór nie pasuje, jeśli dodasz prowadzenie ^
lub (?:^|_)
(cokolwiek jest odpowiednie).
print $1 if $line =~ /^([^_]*)_/;