Recent

Author Topic: How to list the replacement results of regular expressions  (Read 3327 times)

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
How to list the replacement results of regular expressions
« on: October 24, 2017, 03:12:21 pm »
Hi, everybody, I want to perform a regular expression substitution operation, and then list all the places that have been replaced. Is there any way to do that?

such as:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   RegExpr;
  5.  
  6. var
  7.   Str: string;
  8. begin
  9.   Str := ReplaceRegExpr('([0-9]+).([0-9]+)', '123_45_678_9', '$2---$1', True);
  10.   Writeln('Str = ', Str);
  11.   Writeln('Replaced List ...');
  12. end.

Result like this:
Code: [Select]
Str = 45---123_9---678
45---123, start=0, length=8
9---678, start=9, length=7

Thaddy

  • Hero Member
  • *****
  • Posts: 19609
  • Glad to be alive.
Re: How to list the replacement results of regular expressions
« Reply #1 on: October 24, 2017, 03:27:01 pm »
Yes, but that  is not as easy as you think:
- either needs some ( complex) code written by you
- or needs a  diff engine (there are many) that implement that complex code for you....

It is not for the lazy...
Any "programmer" that knows only one programming language is not a programmer

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12620
  • Debugger - SynEdit - and more
    • wiki
Re: How to list the replacement results of regular expressions
« Reply #2 on: October 24, 2017, 05:08:16 pm »
Don't use ReplaceRegExpr

Write your own loop that use regex matching, and find each match.
For each found match:
- replace it (you have start and length)
- add it to your list.

Continue the matching in the next loop iteration, from the end of the replacement. (Hint move the already matched and the replaced parts to a new string, and remove them from the source)

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
Re: How to list the replacement results of regular expressions
« Reply #3 on: October 24, 2017, 05:21:23 pm »
Yes, but that  is not as easy as you think:
- either needs some ( complex) code written by you
- or needs a  diff engine (there are many) that implement that complex code for you....

It is not for the lazy...

Thank you, Thaddy, I don't know how to use diff engine, I've never used it. I thought out a mathed to implemente my needs, but I don't know if it meets all the circumstances, Can someone help me check it out?

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   Classes,
  7.   RegExpr;
  8.  
  9. var
  10.   SourceStr, TargetStr: string;
  11.   Pattern, ReplaceStr, ReplacedOne, MiddleString: string;
  12.   SroucePos, TargetPos: integer;
  13.   expr: TRegExpr;
  14.   Found: boolean;
  15.  
  16. begin
  17.   SourceStr := 'abc123_45_678_9_876_54_3_2_1def';
  18.   Pattern := '([0-9]+).([0-9]+)';
  19.   ReplaceStr := '$2---$1';
  20.   SroucePos := 1;
  21.   TargetPos := 0;
  22.   expr := TRegExpr.Create(Pattern);
  23.  
  24.   Found := expr.Exec(SourceStr);
  25.   while Found do
  26.   begin
  27.     // Replace one string that was found
  28.     ReplacedOne := ReplaceRegExpr(Pattern, expr.Match[0], ReplaceStr, true);
  29.     // Get the string not matched(middle string)
  30.     MiddleString := copy(SourceStr, SroucePos, expr.MatchPos[0] - SroucePos);
  31.     // Get the entire replacement result
  32.     TargetStr := TargetStr + MiddleString + ReplacedOne;
  33.     // Get the starting position of the middle string
  34.     SroucePos := expr.MatchPos[0] + expr.MatchLen[0];
  35.     // Get the position of the replaced string
  36.     TargetPos := TargetPos + Length(MiddleString);
  37.     writeln(ReplacedOne, ' start=', TargetPos, ' lengh=', Length(ReplacedOne));
  38.     // Get the position of the next replaced string
  39.     TargetPos := TargetPos + Length(ReplacedOne);
  40.     Found := expr.ExecNext;
  41.   end;
  42.   expr.Free;
  43.   // Get the last unmatched string
  44.   MiddleString := copy(SourceStr, SroucePos, length(SourceStr) - SroucePos + 1);
  45.   // Get the entire replacement result
  46.   TargetStr := TargetStr + MiddleString;
  47.   writeln('str = ',TargetStr);
  48. end.

Result:
Code: [Select]
45---123 start=3 lengh=8
9---678 start=12 lengh=7
54---876 start=20 lengh=8
2---3 start=29 lengh=5
str = abc45---123_9---678_54---876_2---3_1def

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
Re: How to list the replacement results of regular expressions
« Reply #4 on: October 24, 2017, 05:24:32 pm »
Don't use ReplaceRegExpr

Write your own loop that use regex matching, and find each match.
For each found match:
- replace it (you have start and length)
- add it to your list.

Continue the matching in the next loop iteration, from the end of the replacement. (Hint move the already matched and the replaced parts to a new string, and remove them from the source)

I'm sorry! I just saw your reply (I replied very slowly, every sentence I have to use translation software translated into English, and then check it again, including comments in the code). Thank you, Martin_fr, Thank you for your help!
« Last Edit: October 24, 2017, 06:06:28 pm by tomitomy »

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
Re: How to list the replacement results of regular expressions
« Reply #5 on: November 03, 2017, 03:23:57 am »
I'm sorry, I did not practice before posting. I originally had a similar idea, but I do not know how to replace only one search result and get the replaced content. I think my idea can not be achieved, so I come here Post for help. When I see Thaddy's reply, I want to write out my rough idea first, and then ask "How to replace only one search result and get replaced content", but when I wrote that, I found that I can use "ReplaceRegExpr(Pattern, expr.Match[0], ReplaceStr, true)" to achieve, so I continue to write it, and then come back to reply, but I do not know if this code will run perfectly correctly, because "expr.Match[0]" loses its context, I do not know if "ReplaceRegExpr" will get exactly the right result.

I'm very sorry, Thaddy and Martin_fr, I will think carefully and practice seriously before posting at next time. thank you both for your help!

 

TinyPortal © 2005-2018