2016-05-24 25 views
9

Từ những gì tôi có thể thu thập từ các tài liệu Pharo trên regex, tôi có thể xác định một đối tượng biểu hiện thường xuyên như:Capture chuỗi thay thế regex

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

Và tôi có thể thay thế các regex phù hợp với một chuỗi qua này:

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

Điều này sẽ dẫn đến: `'meh blah meh'.

Cho đến nay, rất tốt. Nhưng tôi muốn thay thế 'bar' và để lại tiền tố một mình. Do đó, tôi cần một biến để xử lý parenthetical được chụp:

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

Và tôi muốn có kết quả: 'foomeh blah remeh'. Tuy nhiên, điều này chỉ mang lại cho tôi: '%1meh blah %1meh'. Tôi cũng đã thử sử dụng \1 hoặc \\1 hoặc $1 hoặc {1} và nhận thay thế chuỗi chữ, ví dụ:, '\1meh blah \1meh' là kết quả.

tôi có thể làm điều này một cách dễ dàng đủ trong GNU Smalltalk với:

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

Nhưng tôi không thể tìm thấy bất cứ nơi nào trong tài liệu regex Pharo mà nói với tôi làm thế nào tôi có thể làm điều này trong Pharo. Tôi đã thực hiện một loạt các googling cho Pharo regex là tốt, nhưng không bật lên bất cứ điều gì. Đây có phải là phần khả năng của lớp RxMatcher hay một số lớp Pharo regex khác không?

+0

có vẻ như Pharo không hỗ trợ thay thế với các nhóm chụp – rock321987

+0

Vâng, bạn đã thử các phong cách backreferencing thông thường? Giống như '\ 1', hoặc' \\ 1' hoặc '$ 1' (có lẽ, với' matchesReplacedWith')? Các nhóm chụp được hỗ trợ, rõ ràng từ những gì phù hợp có thể làm trong Pharo, nhưng không có gợi ý về việc liệu các hỗ trợ ngược có được hỗ trợ như các phần của các mẫu thay thế hay không. –

+1

@ WiktorStribiżew Có, tôi đã thử '\ 1',' \\ 1' và '$ 1'. Trong mỗi trường hợp, sự thay thế là chuỗi chữ. Tôi cập nhật câu hỏi của tôi cho thấy những nỗ lực đó. Tôi thấy các nhóm chụp được hỗ trợ theo như kết hợp đi. Có các ví dụ trong tài liệu để chụp và liệt kê các ảnh chụp. Tuy nhiên, không có gì về backreferencing chúng trong một chuỗi thay thế. Điều này có vẻ cơ bản để regex tìm/thay thế cho tôi, vì vậy tôi ngạc nhiên là nó không được hỗ trợ. – lurker

Trả lời

1

Sau khi thử nghiệm một chút với lớp RxMatcher, tôi đã thay đổi sau vào RxMatcher#copyStream:to:replacingMatchesWith: selector:

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] 

Và sau đó "tiếp cận" mục:

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. 

Với sửa đổi này, tôi có thể thực hiện tìm kiếm trong chuỗi thay thế bằng cách sử dụng mẫu Smalltalk String#format: cho đối số:

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

Kết quả trong:

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

Bạn đã kiểm tra trợ giúp Regex chưa? Không có #replacingAllRegex:, nhưng các khớp có #subexpression:

+0

Đây có phải là một bình luận không? ;) Tôi đọc tất cả các tài liệu trực tuyến về Pharo regex tôi có thể tìm thấy (mà là khá nhiều tất cả các trường hợp tương tự nhắc lại). Tôi biết không có '#replacingAllRegex:' trong Pharo.Tôi đã trích dẫn đó là một ví dụ về những gì tôi có thể làm trong GNU Smalltalk. Tôi biết matcher có '#subexpression:' nhưng không có bộ chọn nào để thực hiện thay thế regex có tham chiếu đến các biểu thức subexpression đó và chúng tồn tại trong các thư viện regex của các ngôn ngữ khác (bao gồm cả GNU Smalltalk). Nếu tôi nhầm, bạn có thể cho tôi xem một ví dụ không? – lurker