1

I need help a with building a regex for extracting a particular string and manipulating it. Here's the example

Actual Input:

( 12s ) Agent K: Hello Guest, How are you doing today?<br> <br>How Can I help<br>
( 18s ) Guest:   Hello there! Need access to XYZ<br>
( 53s ) Agent K: Granted the access<br>
( 1m 9s ) Guest: Ok thanks, Agent K<br>

I want to identify the appearances of "Agent K:", "Guest:" and all timings coming within brackets and manipulate it to

<b>Agent K:</b>.12s Hello Guest, How are you doing today?<br> <br>How Can I help<br>
<b>Guest:</b>.18s   Hello there! Need access to XYZ<br>
<b>Agent K:</b>.53s Granted the access<br>
<b>Guest:</b>.1m 9s Ok thanks, Agent K<br>

I started writing regex function to identify the appearances of ) Agent K: and ) Guest: so that I'm uniquely identifying their places. For that, I'm using below which returns true

string htmlValue = '<br>( 15s ) Agent K: Test Message from user';

string s1 = ') Agent K:';

Boolean found = Pattern.compile('(?i)' + Pattern.quote(s1)).matcher(htmlValue).find();

But I'm not sure how I can move next to start manipulating it. Any help is greatly appreciated!

2

You can use String.replaceAll to do this in one tidy step:

String output = input.replaceAll(
  '(?m)^\\s*\\(\\s*(.+?)\\s*\\)\\s*(.+?:)\\s*\\s*(.+)\\s*$',
  '<strong>$2</strong>.$1 $3'
);

Here's an example output:

String input = '( 12s ) Agent K: Hello Guest, How are you doing today?<br> <br>How Can I help<br>\n( 18s ) Guest:   Hello there! Need access to XYZ<br>\n( 53s ) Agent K: Granted the access<br>\n( 1m 9s ) Guest: Ok thanks, Agent K<br>';
String output = input.replaceAll(
  '(?m)^\\s*\\(\\s*(.+?)\\s*\\)\\s*(.+?:)\\s*\\s*(.+)\\s*$',
  '<strong>$2</strong>.$1 $3'
);
System.debug(output);

Result:

<strong>Agent K:</strong>.12s Hello Guest, How are you doing today?<br> <br>How Can I help<br>
<strong>Guest:</strong>.18s Hello there! Need access to XYZ<br>
<strong>Agent K:</strong>.53s Granted the access<br>
<strong>Guest:</strong>.1m 9s Ok thanks, Agent K<br>

There's a ton of regex here, but it's simple. I'll break it down:

  • ( and ) create "numbered capture groups"
  • (?m) multiline mode, matches newlines with ^ and $
  • ^ Start of a line (in beginning position)
  • $ End of a line (in end position)
  • \\s* Zero or more spaces (we use this a lot to skip whitespace)
  • \\( and \\), literal parentheses
  • (.+?) Match any character sequence, but non-greedy (so, up to the next )).
  • (.+?:) match any sequence ending in :.
  • (.+) match to end of line

And for the replacement string, $1 refers to the first capture group, $2 to the second group, etc.

P.S. <b> and <i> are strongly discouraged in modern HTML. You should use <strong> for bold emphasis (a keyword or heavy emphasis, a concept that must be understood), and <i> should now be <em> for emphasis.

9
  • Possibly worth noting that <strong> should be preferred over <b> in most cases.
    – Adrian Larson
    May 13 '21 at 18:19
  • @AdrianLarson Fair, semantics are important in HTML, this was more a focus on the technique.
    – sfdcfox
    May 13 '21 at 18:20
  • Absolutely, I figured as much.
    – Adrian Larson
    May 13 '21 at 18:21
  • @sfdcfox This is extremely helpful.. Thank you so much for this and especially breaking it down with explanation. It works like a charm! May 14 '21 at 8:58
  • @sfdcfox I have one small issue with it. My each message doesn't end with \n and it ends something like this in actual ( 12s ) Agent K: Test msg <br>( 14s ) Guest: Reply msg <br> some on next line <br>( 18s ) Agent K: New msg Hence I believe the last group (.+) that is looking until end of line need a change. Could you please suggest for that too? I tried few things but doesn't work well May 14 '21 at 10:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.