0

I have this input string

Click ##$#here||action1#$## to do action A
and Click ##$#here||action2#$## to do action B 
and Click ##$#here||action3#$## to do action C

And I need the output strnig as

Click here to do action A
and Click here to do action B
and Click here to do action C

##$#here||action1#$## is an opcode pattern with "here" is replacement_string that replaces the whole opcode pattern and the "action 1" is the underlying action that has to be performed when user clicks on the "here" string (Hyper Link)

TRIED

String msg =Click ##$#here||action1#$## to do action A
and Click ##$#here||action2#$## to do action B 
and Click ##$#here||action3#$## to do action C;

String pattern1 = "##$#", pattern2 = "#$##";

String regexString = Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2);
Pattern pattern = Pattern.compile(regexString);
Matcher matcher = pattern.matcher(msg);

while (matcher.find()) {
    String action = matcher.group(1);
    final String replaceAction[] = action.split("\\|\\|");
    String display = msg.replace(pattern1 + action + pattern2, replaceAction[0]);

    SpannableString ss = new SpannableString(display);
    ClickableSpan clickableSpan = new ClickableSpan() {
        @Override
        public void onClick(View textView) {
            Log.e("CLICKED", "CLICKED");
            Log.e("Action Intent", replaceAction[1]);
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setUnderlineText(true);
        }
    };

    ss.setSpan(clickableSpan, display.indexOf(replaceAction[0]),
            display.indexOf(replaceAction[0]) + replaceAction[0].length(),
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    testTV.append(ss);
    testTV.setMovementMethod(LinkMovementMethod.getInstance());
}

The above code sets the testTV with the string of

Click here to do action A
and Click ##$#here||action2#$## to do action B 
and Click ##$#here||action3#$## to do action C

Click ##$#here||action1#$## to do action A
and Click here to do action B 
and Click ##$#here||action3#$## to do action C

Click ##$#here||action1#$## to do action A
and Click ##$#here||action2#$## to do action B 
and Click here to do action C

Any help or a notion would be strongly appreciated!!!

4
  • \#.+\# or \#.*\# should work for pattern matching. Commented Mar 4, 2016 at 6:35
  • I've added the tried code. Please check again Commented Mar 4, 2016 at 6:39
  • Why don't you just use the replace API to replace the sub-string with a new string? Why is a pattern selection needed here? Commented Mar 4, 2016 at 6:48
  • I think I got it correct with matching and spitting. But the problem seems to be appending the text message in the textView. How do I get It correct. Just the way I've in the example above? Commented Mar 4, 2016 at 6:49

3 Answers 3

2

The following regex will do it:

##\$#(.*?)\|\|action\d+#\$##

You can use the replaceAll() method like this:

str.replaceAll("##\\$#(.*?)\\|\\|action\\d+#\\$##", "$1")

See this regex101 demo.


UPDATE

The problem is that you're appending the entire msg to textTV on each iteration of find(). You need to build it up incrementally.

Something like this:

Pattern p = Pattern.compile("##\\$#(.*?)\\|\\|(.*?)#\\$##");
Matcher m = p.matcher(msg);
int prevEnd;
for (prevEnd = 0; m.find(); prevEnd = m.end()) {
    String plainText = msg.substring(prevEnd, m.start());
    String linkText = m.group(1);
    String action = m.group(2);

    SpannableString ss = new SpannableString(plainText + linkText);
    ClickableSpan clickableSpan = new ClickableSpan() {
        // code here
    };
    ss.setSpan(clickableSpan, plainText.length(), ss.length(),
               Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    testTV.append(ss);
    testTV.setMovementMethod(LinkMovementMethod.getInstance());
}
if (prevEnd < msg.length()) {
    testTV.append(msg.substring(prevEnd));
}
Sign up to request clarification or add additional context in comments.

3 Comments

I appreciate your help. But, ##\$#(.*?)\|\|action\d+#\$## is not the pattern I was looking for. B'cos, replace_string and action could be any characters in unicode. The actual pattern looks like this. ##$#replace_string||action_string#$##
By the way, is the argument $1 means (.*?) ?
@SamuelRobert Correct. See appendReplacement()
0

You can try to assign the updated value in the string msg inside the loop like msg = display; after the statement,

String display = msg.replace(pattern1 + action + pattern2, replaceAction[0]);

1 Comment

That did not help buddy.. :-(
0

After experimenting with it for an hour I found out that the working solution is

    String regexString = Pattern.quote(pattern1) + "(.*?)" + "\\|\\|" + "(.*?)" + Pattern.quote(pattern2);
    Pattern pattern = Pattern.compile(regexString);
    Matcher matcher = pattern.matcher(msg);

    while (matcher.find()) {
        String replace = matcher.group(1); //Replacement string
        String action = matcher.group(2);  //Action String

        msg = msg.replaceFirst(regexString, replace);
    }

Log.e ("Display Message", msg);

1 Comment

This is essentially what I was suggesting you to do. The idea was that since the replacement was working just once, you replace the original message string with the one with the substituted regex. However, whatever way works for you is fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.