2017-05-10 16 views
6

Rozważ ten skrypt, który jest oparty na odpowiedzi na SO 267399 o analizie liczb rzymskich , chociaż przetwarzanie liczb rzymskich jest przypadkowe dla tego pytania o numerze .Co oznacza znak zapytania (? ^: ...) w postaci łańcucha znaków Perl qr // Regex?

#!/usr/bin/env perl 
# 
# Based on answer to SO 0026-7399 

use warnings; 
use strict; 

my $qr1 = qr/(?i:M{1,3})/; 
my $qr2 = qr/(?i:C[MD]|D?C{1,3})/; 
my $qr3 = qr/(?i:X[CL]|L?X{1,3})/; 
my $qr4 = qr/(?i:I[XV]|V?I{1,3})/; 

print "1000s: $qr1\n"; 
print " 100s: $qr2\n"; 
print " 10s: $qr3\n"; 
print " 1s: $qr4\n"; 

# This $qr is too simple — it matches the empty string 
#my $qr = qr/($qr1?$qr2?$qr3?$qr4?)/; 

my $qr = qr/\b((?:$qr1$qr2?$qr3?$qr4?)|(?:$qr2$qr3?$qr4?)|(?:$qr3$qr4?)|(?:$qr4))\b/; 

print " Full: $qr\n"; 

while (<>) 
{ 
    chomp; 
    print " Line: [$_]\n"; 
    while ($_ =~ m/$qr/g) 
    { 
     print "Match: [$1] found in [$_] using qr//\n"; 
    } 
} 

W poniższym pliku danych pierwsze trzy wiersze zawierają numer rzymski.

mix in here 
no mix in here 
mmmcmlxxxix 
minimum 

Uruchomiony z (dom zbudowany) Perl 5.22.0 na komputerze Mac z systemem MacOS teraz Sierra 10.12.4, mam wyjścia jak to (ale wersja Perl nie jest krytyczna):

1000s: (?^:(?i:M{1,3})) 
100s: (?^:(?i:C[MD]|D?C{1,3})) 
    10s: (?^:(?i:X[CL]|L?X{1,3})) 
    1s: (?^:(?i:I[XV]|V?I{1,3})) 
Full: (?^:\b((?:(?^:(?i:M{1,3}))(?^:(?i:C[MD]|D?C{1,3}))?(?^:(?i:X[CL]|L?X{1,3}))?(?^:(?i:I[XV]|V?I{1,3}))?)|(?:(?^:(?i:C[MD]|D?C{1,3}))(?^:(?i:X[CL]|L?X{1,3}))?(?^:(?i:I[XV]|V?I{1,3}))?)|(?:(?^:(?i:X[CL]|L?X{1,3}))(?^:(?i:I[XV]|V?I{1,3}))?)|(?:(?^:(?i:I[XV]|V?I{1,3}))))\b) 
Line: [mix in here] 
Match: [mix] found in [mix in here] using qr// 
Line: [no mix in here] 
Match: [mix] found in [no mix in here] using qr// 
Line: [mmmcmlxxxix] 
Match: [mmmcmlxxxix] found in [mmmcmlxxxix] using qr// 
Line: [minimum] 

Jedyną częścią wyjścia, że ​​nie rozumieją, daszek ^ w notacji z (?^:…).

Szukałem w dokumentacji Perla dla perlre i perlref a nawet sekcji perlop na „regex cytując podobny operatorów” nie widząc ten zilustrowany lub wyjaśnione. (Sprawdziłem również środki sugerowane przez SO kiedy zadajesz pytanie o regexes Ciąg (?^: jest starannie zaprojektowany, aby dać wyszukiwarkom conniptions.).

Istnieją dwie części do mojego pytania:

  1. Co to jest znaczenie kija w (?^:…) i co spowodowało, że zostało ono dodane do regexów qr//?
  2. Jeśli ma to znaczenie, w jaki sposób można go powstrzymać przed dodaniem do wyrażeń regularnych qr//?

Odpowiedz

8

Zasadniczo oznacza to, że obowiązują flagi domyślne (nawet jeśli zostaną interpolowane na wyrażenie regularne, które określa inaczej). Zanim został wprowadzony, qr wyprodukowałby coś takiego jak (?-ismx:, a nowa flaga dodawana do Perla wprowadziłaby tę zmianę, co powoduje, że testowanie się kończy .

http://perldoc.perl.org/perlre.html#Extended-Patterns: "?"

Począwszy Perl 5.14, jest "^" (daszek lub okalającej akcent) niezwłocznie po jest skrótowym odpowiednikiem d-imnsx. Flagi (z wyjątkiem "d") mogą podążać za karetą, aby ją przesłonić. Ale znak minus nie jest z nią zgodny.

+0

Huh ... jak to przegapiłem ...? Drat! I dzięki! –

5

To znaczy "ustawić wszystkie flagi (takie jak i, s) do wartości domyślnych", więc

$ perl -le'my $re = "a"; for (qw(a A)) { print "$_: ", /$re/i ? "match" : "no match"; }' 
a: match 
A: match 

$ perl -le'my $re = "(?^:a)"; for (qw(a A)) { print "$_: ", /$re/i ? "match" : "no match"; }' 
a: match 
A: no match 

Jest używany głównie do reprezentowania wzorców stworzonych przez qr //.

$ perl -le'my $re = qr/a/; print $re; for (qw(a A)) { print "$_: ", /$re/i ? "match" : "no match"; }' 
(?^:a) 
a: match 
A: no match 

$ perl -le'my $re = qr/a/i; print $re; for (qw(a A)) { print "$_: ", /$re/i ? "match" : "no match"; }' 
(?^i:a) 
a: match 
A: match