2016-05-24 23 views
9

Von dem, was ich aus der Pharo Dokumentation auf regex sammeln kann, kann ich einen regulären Ausdruck Objekt definieren, wie:Capture-String in regex Ersatz

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

Und ich kann die abgestimmte regex mit einer Schnur über diese ersetzen:

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

Was ergibt: `'mah blah meh'.

So weit, so gut. Aber ich möchte die 'bar' ersetzen und das Präfix allein lassen. Daher brauche ich eine Variable, die die erfasste, in Klammern zu handhaben:

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

Und ich mag das Ergebnis: 'foomeh blah remeh'. Allerdings gibt mir das nur: '%1meh blah %1meh'. Ich habe auch versucht, \1 oder \\1 oder $1 oder {1} zu verwenden, und bekam den Literalstringersatz, z., '\1meh blah \1meh' als Ergebnis.

Ich kann dies in GNU Smalltalk leicht genug tun mit:

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

Aber ich kann nicht überall in der Pharo regex Dokumentation finden, das mir sagt, wie ich dies in Pharo tun kann. Ich habe auch für Pharo regex gegoogelt, aber nichts gefunden. Ist diese Fähigkeit Teil der RxMatcher-Klasse oder einer anderen Pharo-Regex-Klasse?

+0

es scheint pharo Ersatz nicht unterstützt mit Gruppen Erfassung – rock321987

+0

Nun, haben Sie versucht, die üblichen Rückreferenzierung Stile? Wie '\ 1' oder' \\ 1' oder '$ 1' (vielleicht mit' matchesReplacedWith')? Capturing-Gruppen werden unterstützt. Es ist klar, was Matching in Pharo machen kann, aber es gibt keinen Hinweis darauf, ob Backreferences als Teile von Ersatzmustern unterstützt werden. –

+1

@ WiktorStribiżew Ja, ich habe '\ 1',' \\ 1' und '$ 1' auch versucht. In jedem Fall war die Ersetzung die Literalfolge. Ich habe meine Frage aktualisiert, die diese Versuche anzeigt. Ich sehe, dass das Einfangen von Gruppen unterstützt wird, soweit das Matching geht. In der Dokumentation finden Sie Beispiele zum Erfassen und Aufzählen der Captures. Es wird jedoch nichts über die Rückverweisung in einer Ersetzungszeichenfolge gesagt. Dies scheint grundlegend zu sein, um Regex zu finden/zu ersetzen, also bin ich überrascht, dass es nicht unterstützt wird. – lurker

Antwort

1

Nach einem wenig mit der RxMatcher Klasse experimentieren, ich die folgenden Änderung an den RxMatcher#copyStream:to:replacingMatchesWith: Selektor gemacht:

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] 

Und dann „Zugriff“ Kategorie:

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. 

Mit dieser Änderung kann ich einen Lookback in der Ersetzungszeichenfolge mit dem Smalltalk String#format: Muster für Argumente:

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

Ergebnisse in:

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

Haben Sie die Regex-Hilfe überprüft? Es gibt keine #replacingAllRegex:, aber der Matcher hat #subexpression:

+0

Ist das nicht wirklich ein Kommentar? ;) Ich lese alle Online-Dokumentation über Pharo Regex die ich finden konnte (die sind ziemlich alle die gleichen Instanzen wiederholt). Ich weiß, dass es in Pharo kein '# replacingAllRegex:' gibt.Ich habe das als ein Beispiel dafür angeführt, was ich in GNU Smalltalk tun könnte. Ich weiß, dass der Matcher '#subpression:' hat, aber es gibt keinen Selektor, um eine Regex-Ersetzung durchzuführen, die Verweise auf diese Teilausdrucksübereinstimmungen enthält und in Regex-Bibliotheken anderer Sprachen existiert (einschließlich der GNU Smalltalk). Wenn ich mich irre, kannst du mir ein Beispiel zeigen? – lurker