在正则表达式替换中捕获字符串
Capture string in regex replacement
根据我从 Pharo 正则表达式文档中收集到的信息,我可以定义一个正则表达式对象,例如:
re := '(foo|re)bar' asRegex
我可以通过这个用字符串替换匹配的正则表达式:
re copy: 'foobar blah rebar' replacingMatchesWith: 'meh'
这将导致:`'meh blah meh'.
到目前为止,还不错。但我想替换 'bar'
并单独保留前缀。因此,我需要一个变量来处理捕获的括号:
re copy: 'foobar blah rebar' replacingMatchesWith: '%1meh'
我想要结果:'foomeh blah remeh'
。然而,这只是给我:'%1meh blah %1meh'
。我还尝试使用 </code>、或 <code>\1
、或 </code>、或 <code>{1}
并得到了文字字符串替换,例如、'meh blah meh'
结果。
我可以在 GNU Smalltalk 中轻松完成此操作:
'foobar blah rebar' replacingAllRegex: '(foo|re)bar' with: '%1meh'
但我在 Pharo 正则表达式文档中找不到任何地方告诉我如何在 Pharo 中执行此操作。我也对 Pharo 正则表达式进行了大量谷歌搜索,但没有找到任何结果。此功能是 RxMatcher class 或其他 Pharo 正则表达式 class 的一部分吗?
您查看正则表达式帮助了吗?没有#replacingAllRegex:
,但是匹配器有#subexpression:
在对 RxMatcher
class 进行了一些试验后,我对 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]
然后是"accessing"类别:
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.
通过此修改,我可以使用 Smalltalk String#format:
参数模式在替换字符串中进行回顾:
re := '((foo|re)ba(r|m))' asRegex
re copy: 'foobar meh rebam' replacingMatchesWith: '{2}bu{3} (was {1})'
结果:
'foobur (was foobar) meh rebum (was rebam)'
根据我从 Pharo 正则表达式文档中收集到的信息,我可以定义一个正则表达式对象,例如:
re := '(foo|re)bar' asRegex
我可以通过这个用字符串替换匹配的正则表达式:
re copy: 'foobar blah rebar' replacingMatchesWith: 'meh'
这将导致:`'meh blah meh'.
到目前为止,还不错。但我想替换 'bar'
并单独保留前缀。因此,我需要一个变量来处理捕获的括号:
re copy: 'foobar blah rebar' replacingMatchesWith: '%1meh'
我想要结果:'foomeh blah remeh'
。然而,这只是给我:'%1meh blah %1meh'
。我还尝试使用 </code>、或 <code>\1
、或 </code>、或 <code>{1}
并得到了文字字符串替换,例如、'meh blah meh'
结果。
我可以在 GNU Smalltalk 中轻松完成此操作:
'foobar blah rebar' replacingAllRegex: '(foo|re)bar' with: '%1meh'
但我在 Pharo 正则表达式文档中找不到任何地方告诉我如何在 Pharo 中执行此操作。我也对 Pharo 正则表达式进行了大量谷歌搜索,但没有找到任何结果。此功能是 RxMatcher class 或其他 Pharo 正则表达式 class 的一部分吗?
您查看正则表达式帮助了吗?没有#replacingAllRegex:
,但是匹配器有#subexpression:
在对 RxMatcher
class 进行了一些试验后,我对 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]
然后是"accessing"类别:
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.
通过此修改,我可以使用 Smalltalk String#format:
参数模式在替换字符串中进行回顾:
re := '((foo|re)ba(r|m))' asRegex
re copy: 'foobar meh rebam' replacingMatchesWith: '{2}bu{3} (was {1})'
结果:
'foobur (was foobar) meh rebum (was rebam)'