2014-09-08 16 views
5

Jeśli Metaznak ? mecze poprzedniego elementu zero lub jedno czasie, todlaczego tylko pierwsza litera jest zwracana przez funkcję dopasowania?

dlaczego

"ab".match(/a?/) 

zwraca ["a"],

ale

"ab".match(/b?/) 

powraca [""]

?

+2

Dlaczego więc [""] nie zostanie zwrócony w pierwszym przypadku? – valeryan

+0

(Jeśli ktoś zapyta: dlaczego nie?) – valeryan

+0

'?' Jest chciwe, więc będzie pasować tak dużo jak to tylko możliwe w pozycji, w której się znajduje. –

Odpowiedz

0

Zastanawiam się, czy mogę wyjaśnić to lepiej z następującej analogii.

Wyobraź sobie przyjaznego kasjera fast food, kolejkę głodnych klientów i rodzaj przenośnika taśmowego pełnego hamburgerów. Ona oferuje hamburgery jeden po drugim każdemu klientowi, aż wszystkie są szczęśliwe (jeśli jakieś hamburgery zostaną, to nie ma znaczenia). Następnie zapisuje listę wszystkich klientów i przekazuje tę listę swojemu przełożonemu.Kasjer będzie silnikiem regex, hamburgery są symbolami z łańcucha wejściowego, a klienci są wyrażeń regularnych regex. Manager jest funkcją dopasowania.

Na przykład podczas dopasowywania abbc przeciwko /[a]b+./ scena odgrywa tak:

 

("[a]", "b+" and "." stand the queue) 

Cashier: Hi, "[a]", would you like "a"? 
[a]: Sure, thanks! 
C: would you also like "b"? 
[a]: No, thanks, I'm fine (goes). 
C: Hi, "b+", would you like "b"? 
b+: Sure. 
C: Would you like another "b"? 
b+: Yes, I'm hungry. 
C: Can I offer you "c" also? 
b+: Not my kind of thing (goes). 
C: Hi, ".", I have only one "c" left. 
.: I don't care what it is, just gimme it (goes). 
C: All served! Looks like I'll get the job! 

Jeśli zdarza się, że kasjer nie jest w stanie zadowolić klienta, ma prawo zażądać poprzednią i poprosić by oddać to, co mają. Nazywa się to "cofaniem". Rozważmy:

 

"abx" against /.+[xyz]/ 

C: Hi, ".+", would you like "a"? 
.+: Yum-yum! 
C: How about "b"? 
.+: Yum-yum! 
C: And "x"? 
.+: Yum-yum! 
C: My belt is empty! (.+ goes) 
C: Hi, "[xyz]", I'm afraid I'm sold out. 
[xyz]: That's out of the question. Can I see the manager? 
C: Wait, I think we can sort it out! (calls ".+") 
C (to ".+"): Sorry pal, you know, this nasty guy over there... 
       I wonder if you could you give me back your last one? 
.+: No prob... (gives "x" back) 
C (to "[xyz]"): I've got something for you. Do you eat "x"? 
[xyz]: If you want to get anything done in this country 
     you've got to complain until you are blue in the mouth 
     (gets his "x" and goes in a rage) 
C: Gosh, what a day... 

teraz z powrotem do swoich przykładach:

 

Scene I. "ab" against /a?/ 
Burgers: a and b, customer: a? 

C: Hi, "a?" would you like "a"? 
a?: Sure, thanks. 
C: Can I offer you "b" also? 
a?: No, thanks, I'm fine (goes). 
Manager: I need the inventory report, now! 
C: Here you go: "a?" got "a", we have "b" and "c" left. 

Scene II. "ab" against /b?/ 
Burgers: a and b, customer: b? 

C: Hi, "b?" would you like "a"? 
b?: No thanks, but that's no problem. (goes). 
M: Status? 
C: "b?" got nothing and went. a, b, c are still there. 

Więc zasadniczo b? jest bardzo ładne (i nie jest szczególnie głodny) facet, a on jest szczęśliwy, nawet jeśli kasjer nie ma nic dla niego. Jeśli jest jedyną osobą w kolejce, to jej szczęśliwy dzień!

+0

Wyobraź sobie najbardziej szczęśliwą scenę (dla klienta, kasjera, a szczególnie managera): "" przeciw/.*/ – valeryan

+0

@ user3119308:;)) Każda analogia jest tylko analogią. Nie bierz tego zbyt poważnie! – georg

+0

@ user3119308: Nie sądzę, że to jest szczęśliwy. Sklep nic nie sprzedaje, a nawet gdyby tak było, jest nieskończenie głodny klient, który blokuje wszystko ... – Bergi

8

Bo to pierwszy mecz. Wyrażenie próbuje najpierw dopasować w pozycji 0, gdzie wyrażenie regularne # 1 pasuje do a, a wyrażenie regularne # 2 pasuje do pustego łańcucha. Następnie próbuje dopasować na pozycji 1, gdzie regex # 1 pasuje do pustego ciągu, a wyrażenie regularne # 2 pasuje do litery b. W końcu próbuje dopasować na pozycji 3, gdzie oba wyrażenia regularne pasują do pustego ciągu.

Porównaj zwróconych mecze z globalnej flagi:

> "ab".match(/a?/) 
["a"] 
> "ab".match(/a?/g) 
["a", "", ""] 
> "ab".match(/b?/) 
[""] 
> "ab".match(/b?/g) 
["", "b", ""] 

dlaczego nie [ ""] jest zwrócony w pierwszym przypadku?

Ze względu na mechanizmy backtracking. Podczas próby dopasowania w dowolnej pozycji silnik będzie usiłował usilnie próbować zmierzyć wszystkie litery wyrażenia regularnego na literach ciągu znaków. Gdy dojdzie do końca regexu tą metodą, dopasowanie się udało. Gdy litera nie pasuje, próbuje wrócić do wyrażenia regularnego, aby sprawdzić, czy ewentualne pominięcia - przy użyciu modyfikatorów, takich jak * lub ? - lub alternatywy (|) należy rozważyć, a następnie kontynuować od tego momentu .

Przykład: dopasować /b?/ w pozycji 0 "ab":

 
// - "": ✓ 
/b/ - "a": × 
/b?/ - "": ✓ - succeed (end of regex) 
^means here that the "b" token is omitted 

Przykład: dopasować /a?/ w pozycji 0 "ab":

 
// - "": ✓ 
/a/ - "a": ✓ - succeed (end of regex) 

przykład: dopasować /ab?(bc)?/ w pozycji 0 "abc"

 
//  - "": ✓ 
/a/  - "a": ✓ 
/ab/  - "ab": ✓ 
/ab(b)/ - "abc": × 
/ab(bc)?/ - "ab": ✓ - succeed (end of regex) 

1: Zazwyczaj przynajmniej. Wiele smaków regex zapewnia również kwantyfikatory, które są lazy lub possessive, jeśli chcesz kontrolować dokładne zachowanie pasujące. Na przykład: /ab??(bc)?/ pasuje abc w "abc"

+1

+1 ale "pozycja 0" nie wydaje mi się zbyt oczywista. Zwłaszcza jeśli weźmiesz pod uwagę '" ".match (/ a?/G)'. Wydaje mi się, że to połowa odpowiedzi. –

+1

"position 0" jest początkiem łańcucha, tj. Pozostawionym do 'a' w' "ab" '. Masz rację, puste mecze są mylące :-) – Bergi

Powiązane problemy