2016-05-24 14 views
9

Z tego co mogę zebrać z dokumentacji Pharo na regex, mogę określić regularny obiekt określenia takie jak:przechwytywania ciąg zamiennik regex

re := '(foo|re)bar' asRegex 

I mogę zastąpić dopasowany regex z ciągiem przez to:

re copy: 'foobar blah rebar' replacingMatchesWith: 'meh' 

Co spowoduje: `` meh bla meh '.

Jak dotąd, tak dobrze. Ale chcę zastąpić 'bar' i zostawić prefiks sam. Dlatego muszę zmienną obsłużyć przechwycony nawiasach:

re copy: 'foobar blah rebar' replacingMatchesWith: '%1meh' 

I chcę wynik: 'foomeh blah remeh'. Jednak to tylko daje mi: '%1meh blah %1meh'. Próbowałem również użyć \1 lub \\1 lub $1 lubi otrzymałem dosłowny zamiennik ciągu, np. ., '\1meh blah \1meh' w wyniku.

mogę to zrobić dość łatwo w Smalltalk GNU z:

'foobar blah rebar' replacingAllRegex: '(foo|re)bar' with: '%1meh' 

Ale nie mogę znaleźć nigdzie w dokumentacji regex Pharo, który mówi mi, jak mogę to zrobić w Pharo. Zrobiłem też sporo wyszukując dla regexu Pharo, ale niczego nie odkryłem. Czy ta funkcja jest częścią klasy RxMatcher lub innej klasy regex Pharo?

+0

wydaje Pharo nie obsługuje wymianę z przechwytywanie grup – rock321987

+0

Cóż, próbowałeś zwykłe style backreferencing? Jak '\ 1' lub' \\ 1' lub '$ 1' (być może z' matchesReplacedWith')? Grupy przechwytywania są obsługiwane, jest jasne, co może zrobić dopasowanie w Pharo, ale nie ma podpowiedzi, czy odsyłacze wstecz są obsługiwane jako części wzorców zastępczych. –

+1

@ WiktorStribiżew Tak, próbowałem również '\ 1',' \\ 1' i '$ 1'. W każdym przypadku zamiennikiem był łańcuch literowy. Zaktualizowałem moje pytanie wskazujące na te próby. Widzę, że grupy przechwytywania są obsługiwane, o ile dopasowywanie idzie. Istnieją przykłady w dokumentacji do przechwytywania i wyliczania przechwytów. Jednak nie ma nic o odwołaniach do nich w łańcuchu zamiennym. To wydaje się być fundamentalne dla znalezienia/zastąpienia mnie, więc jestem zaskoczony, że nie jest obsługiwany. – lurker

Odpowiedz

1

Po eksperymentach trochę z klasą RxMatcher, zrobiłem następującą modyfikację do selektora RxMatcher#copyStream:to:replacingMatchesWith::

copyStream: aStream to: writeStream replacingMatchesWith: aString 
    "Copy the contents of <aStream> on the <writeStream>, 
    except for the matches. Replace each match with <aString>." 

    | searchStart matchStart matchEnd | 
    stream := aStream. 
    markerPositions := nil. 
    [searchStart := aStream position. 
    self proceedSearchingStream: aStream] whileTrue: [ | ws rep | 
     matchStart := (self subBeginning: 1) first. 
     matchEnd := (self subEnd: 1) first. 
     aStream position: searchStart. 
     searchStart to: matchStart - 1 do: 
      [:ignoredPos | writeStream nextPut: aStream next]. 

     "------- The following lines replaced: writeStream nextPutAll: aString ------" 
     "Do the regex replacement including lookback substitutions" 
     writeStream nextPutAll: (aString format: self subexpressionStrings). 
     "-------" 

     aStream position: matchEnd. 
     "Be extra careful about successful matches which consume no input. 
     After those, make sure to advance or finish if already at end." 
     matchEnd = searchStart ifTrue: 
      [aStream atEnd 
       ifTrue: [^self "rest after end of whileTrue: block is a no-op if atEnd"] 
       ifFalse: [writeStream nextPut: aStream next]]]. 
    aStream position: searchStart. 
    [aStream atEnd] whileFalse: [writeStream nextPut: aStream next] 

A potem „dostępu” Kategoria:

subexpressionStrings 
    "Create an array of lookback strings" 
    | ws | 
    ws := Array new writeStream. 
    2 to: (self subexpressionCount) do: [ :n | | se | 
     ws nextPut: ((se := self subexpression: n) ifNil: [ '' ] ifNotNil: [ se ]) ]. 
    ^ws contents. 

Po wprowadzeniu tej modyfikacji mogę powtórzyć ciąg zastępczy za pomocą wzoru Smalltalk String#format: dla argumentów:

re := '((foo|re)ba(r|m))' asRegex 
re copy: 'foobar meh rebam' replacingMatchesWith: '{2}bu{3} (was {1})' 

Wyniki w:

'foobur (was foobar) meh rebum (was rebam)' 
0

Czy sprawdziłeś pomoc Regex? Nie ma #replacingAllRegex:, ale dopasowujący ma #subexpression:

+0

Czy to naprawdę nie jest komentarz? ;) Przeczytałem całą dokumentację online dotyczącą regexu Pharo, które mogłem znaleźć (które są prawie wszystkie tymi samymi przypadkami powtórzonymi). Wiem, że nie ma "#replacingAllRegex:" w Pharo.Cytowałem to jako przykład tego, co mogłem zrobić w GNU Smalltalk. Wiem, że Matcher ma '#subexpression:' ale nie ma selektora, który wykonałby wyrażenie regularne, które zawiera odniesienia do tych dopasowań podwyrażenia i jak istnieją w bibliotekach regex innych języków (w tym GNU Smalltalk). Jeśli się mylę, czy możesz pokazać mi przykład? – lurker

Powiązane problemy