Jaka jest różnica między $ / a $ ¢ w wyrażeniach regularnych?


11

Jak wskazuje tytuł, jaka jest różnica między $/i ? Wydaje się, że zawsze mają tę samą wartość:

my $text = "Hello world";

$text ~~ /(\w+) { say $/.raku } (\w+)/;
$text ~~ /(\w+) { say $¢.raku } (\w+)/;

Oba dają wynik Dopasuj obiekty o tych samych wartościach. Jaka jest logika używania jednego nad drugim?

Odpowiedzi:


11

Zmienna $/odnosi się do ostatniego dopasowania, podczas gdy zmienna odnosi się do ostatniego najbardziej zewnętrznego dopasowania. W większości podstawowych wyrażeń regularnych, takich jak powyższe, może to być jedno i to samo. Ale jak widać na podstawie wyniku .rakumetody, Matchobiekty mogą zawierać inne Matchobiekty (to, co otrzymujesz, gdy używasz $<foo>lub $1do przechwytywania).

Załóżmy, że zamiast tego mieliśmy następujący regex z ujęciem ilościowym

/ ab (cd { say $¢.from, " ", $¢.to } ) + /

I uruchomiłby, zobaczyłby następujące dane wyjściowe, gdybyśmy dopasowali do „abcdcdcd”:

0 2
0 4
0 6

Ale jeśli zmienimy z używania na $/, otrzymamy inny wynik:

2 2
4 4
6 6

( .toWydaje się, że to trochę nie tak, ponieważ .pos- i - nie są aktualizowane do końca bloku przechwytywania.)

Innymi słowy, zawsze będzie odnosił się do tego, jaki będzie twój ostateczny obiekt dopasowania (tj. ), Abyś mógł przechodzić przez złożone drzewo przechwytywania w wyrażeniu regularnym dokładnie tak, jak zrobiłbyś to po zakończeniu pełnego dopasowania. W powyższym przykładzie możesz po prostu zrobić, aby odnieść się do pierwszego dopasowania, drugiego itd.$final = $text ~~ $regex$¢[0]$¢[1]

Wewnątrz bloku kodu wyrażenia regularnego $/będzie odnosić się do najbardziej bezpośredniego dopasowania. W powyższym przypadku jest to dopasowanie do wewnątrz ( )i nie będzie wiadomo o innych dopasowaniach, ani o oryginalnym początku dopasowania: tylko początek ( )bloku. Podaj więc bardziej złożony regex:

/ a $<foo>=(b $<bar>=(c)+ )+ d /

Możemy uzyskać dostęp w dowolnym momencie za pomocą $ ¢ wszystkich footokenów, mówiąc $¢<foo>. Możemy uzyskać dostęp do bartokenów danego fooza pomocą $¢<foo>[0]<bar>. Jeśli wstawimy blok kodu wewnątrz fooprzechwytywania, będzie on mógł uzyskać dostęp do bartokenów za pomocą $<bar>lub $/<bar>, ale nie będzie mógł uzyskać dostępu do innych foos.


1
Och! Zinterpretowałem dokument „Główną różnicą między $/i jest zakres: ten ostatni ma tylko wartość w wyrażeniu regularnym”, co oznacza, że był jedynie śladowym śladem, tak jak Cursorjest. Kiedy czytam twoją odpowiedź, pomyślałem, że to $*TOPja stworzyłem w A możliwej poprawie? sekcja mojej odpowiedzi na pisemne zgłoszenie zastrzeżeń „Dlaczego / jak potrzebna jest dodatkowa zmienna w dopasowywaniu powtarzającego się arbitralnego znaku z grupami przechwytywania?”. Ale moje próby zastąpienia $*TOPprzez nie powiodły się. Czy rozumiesz mój punkt w tej odpowiedzi? Czy potrafisz sprawić, żeby działało?
raiph

Raiph: Tak więc w gramatyce jest odnawiany dla każdego tokena, więc musisz powiedzieć $*TOP := $¢w TOPtokenie, ale to nie pozbawia potrzeby $*TOPvar. Zgadzam się, że byłoby wspaniale móc odnosić się do meczów na najwyższym poziomie. Problemem jest wciąż ten, który zidentyfikujesz: kiedy pozycja / hash dopasowuje wpis do obiektu dopasowania. Podczas używania - co jest na token - wyniki będą z definicji wysyłane, gdy tylko { }napotka blok otaczający .
user0721090601

Interesujące jest dla mnie to, że przy opracowywaniu Binexnie znalazłem gorszego obliczeniowo, aby publikować wyniki meczów natychmiast po ich znalezieniu. Na koniec dnia popychasz / popping albo na buforowaną listę / skrót lub popychasz / popping na listę / skrót. Może jednak istnieć jakieś wewnętrzne przyspieszenie, o którym nie wiem, że jest używane w LTM, co prawdopodobnie jest jego rdzeniem ( { }kończy token na potrzeby LTM, a zatem jest bardziej prawdopodobne, że zostanie uruchomione / przetestowane niż reszta tokena w |grupie)
0721090601

Ahhh Doszedłem do wniosku, że był dynamiczny i byłem zaskoczony, gdy to nie zadziałało. Ale grosz odrzucił teraz, że jest leksykalny, jak mogłem się domyślić, biorąc pod uwagę twoje użycie słowa „najbardziej zewnętrzny” i, jak wyjaśnisz, ustalono na początku każdej reguły.
raiph

Tak więc, iiuc, na początku reguły tworzony jest nowy obiekt dopasowania, który rejestruje pozycję kursora pasującego silnika w oryginalnym ciągu wejściowym, ale poza tym jest pusty. (Prawda?) Wtedy i $/są zobowiązane do tego samego obiektu, a mianowicie tego nowego obiektu mecz, który będzie rejestrował co to mecze regułę i przechwytuje jak postępuje. Następnie, w miarę postępu dopasowywania, pozostaje związany z tym ogólnym obiektem dopasowania, natomiast $/jest odbijany za każdym razem, gdy tworzony jest nowy obiekt dopasowania, więc zawsze odpowiada, jak mówisz, najnowszemu obiektowi dopasowania. Dobrze?
raiph
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.