Sự khác biệt giữa $ / và $ trong regex là gì?


11

Như tiêu đề cho thấy, sự khác biệt giữa $/và là gì? Chúng dường như luôn có cùng giá trị:

my $text = "Hello world";

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

Cả hai đều dẫn đến kết quả Đối tượng có cùng giá trị. Logic trong việc sử dụng cái này hơn cái kia là gì?

Câu trả lời:


11

Biến $/đề cập đến trận đấu gần đây nhất trong khi biến đề cập đến trận đấu ngoài cùng gần nhất. Trong hầu hết các regex cơ bản như trên, đó có thể là một và giống nhau. Nhưng như có thể thấy từ đầu ra của .rakuphương thức, Matchcác đối tượng có thể chứa các Matchđối tượng khác (đó là những gì bạn nhận được khi bạn sử dụng $<foo>hoặc $1để chụp).

Giả sử thay vào đó chúng ta đã có regex sau với một bản chụp được định lượng

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

Và chạy nó sẽ thấy đầu ra sau nếu chúng ta khớp với "abcdcdcd":

0 2
0 4
0 6

Nhưng nếu chúng ta thay đổi từ sử dụng sang $/, chúng ta sẽ nhận được một kết quả khác:

2 2
4 4
6 6

(Lý do .tocó vẻ hơi lạc lõng là vì nó và .pos- không được cập nhật cho đến khi kết thúc khối chụp.)

Nói cách khác, sẽ luôn đề cập đến đối tượng phù hợp cuối cùng của bạn (nghĩa là $final = $text ~~ $regex) để bạn có thể đi qua một cây bắt phức tạp bên trong regex chính xác như bạn đã làm sau khi kết thúc trận đấu đầy đủ. Trong ví dụ trên, bạn có thể chỉ cần làm $¢[0]để chỉ trận đấu đầu tiên, $¢[1]lần thứ hai, v.v.

Bên trong một khối mã regex, $/sẽ đề cập đến trận đấu ngay lập tức nhất. Trong trường hợp trên, đó là trận đấu cho bên trong ( )và sẽ không biết về các trận đấu khác, cũng không phải là điểm bắt đầu ban đầu của trận đấu: chỉ là sự khởi đầu cho ( )khối. Vì vậy, đưa ra một biểu thức phức tạp hơn:

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

Chúng tôi có thể truy cập tại bất kỳ điểm nào bằng cách sử dụng $ ¢ tất cả các foomã thông báo bằng cách nói $¢<foo>. Chúng tôi có thể truy cập barmã thông báo của một foobằng cách sử dụng $¢<foo>[0]<bar>. Nếu chúng tôi chèn một khối mã bên trong bản foochụp, nó sẽ có thể truy cập barmã thông báo bằng cách sử dụng $<bar>hoặc $/<bar>, nhưng nó sẽ không thể truy cập vào các mã khác foo.


1
Ồ! Tôi đã giải thích tài liệu "Sự khác biệt chính giữa $/là phạm vi: cái sau chỉ có một giá trị bên trong regex" có nghĩa chỉ là một dấu vết di tích, giống như vậy Cursor. Khi tôi đọc câu trả lời của bạn, tôi nghĩ sẽ là cái $*TOPtôi tạo ra trong sự cải thiện có thể?phần câu trả lời của tôi cho SO "Tại sao / làm thế nào là một biến bổ sung cần thiết trong việc khớp ký tự tùy ý lặp đi lặp lại với các nhóm bắt giữ?". Nhưng những nỗ lực của tôi để thay thế $*TOPbằng thất bại. Bạn có hiểu quan điểm của tôi trong câu trả lời đó không? Bạn có thể làm cho nó hoạt động?
raiph

Raiph: Vì vậy, trong ngữ pháp, được đổi mới cho mỗi mã thông báo, vì vậy bạn phải nói $*TOP := $¢trong TOPmã thông báo nhưng điều đó không loại bỏ sự cần thiết của $*TOPvar. Tôi đồng ý sẽ thật tuyệt vời khi có thể tham khảo các trận đấu ở cấp cao nhất. Vấn đề cuối cùng vẫn là vấn đề bạn xác định: khi vị trí / hàm băm khớp với bài đăng đối tượng phù hợp. Khi sử dụng - đó là mỗi mã thông báo - kết quả sẽ theo định nghĩa bài đăng ngay khi { }gặp phải khối kèm theo của nó .
user0721090601

Điều thú vị đối với tôi là trong quá trình phát triển Binex, tôi đã không thấy nó trở nên tồi tệ hơn khi đăng kết quả trận đấu ngay khi gặp họ. Vào cuối ngày, bạn đang đẩy / bật vào danh sách / hàm băm được lưu trong bộ nhớ cache hoặc bạn đang đẩy / bật vào danh sách / hàm băm của trận đấu. Tuy nhiên, có thể có một số loại tăng tốc nội bộ mà tôi không biết về việc sử dụng cho LTM có khả năng là cốt lõi của nó (việc { }chấm dứt mã thông báo cho các mục đích của LTM và do đó có nhiều khả năng được chạy / kiểm tra hơn phần còn lại của mã thông báo trong một |nhóm)
user0721090601

À Tôi đã đi đến kết luận là năng động, và đã rất ngạc nhiên khi nó không hoạt động. Nhưng đồng xu bây giờ đã bỏ đi rằng đó là từ vựng, vì tôi có thể đoán được việc bạn sử dụng từ "ngoài cùng", và, như bạn giải thích, được thiết lập khi bắt đầu mỗi quy tắc.
raiph

Vì vậy, iiuc, khi bắt đầu quy tắc, một đối tượng khớp mới được tạo để ghi lại vị trí con trỏ của công cụ khớp trong chuỗi đầu vào ban đầu, nhưng nếu không thì trống. (Phải không?) Sau đó $/bị ràng buộc với cùng một đối tượng, cụ thể là đối tượng đối sánh mới này, sẽ ghi lại những gì quy tắc này khớp và nắm bắt khi tiến triển. Sau đó, khi tiến trình khớp, vẫn bị ràng buộc với đối tượng khớp tổng thể này, trong khi$/ được bật lại mỗi khi một đối tượng khớp mới được tạo, do đó, nó luôn luôn tương ứng, như bạn nói, với đối tượng khớp mới nhất. Đúng?
raiph
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.