Amirhossein
Amirhossein

Reputation: 329

String pattern detection

I want to turn a string into a html tag with a specified pattern like this:

Walking in the !boldstreet

I want to detect the !bold in the string and turn the following word into "<b>street</b>".

    String s = "Walking in the !boldstreet" 
    String result = null;
    String[] styles = {"!bold", "!italic", "!deleted", "!marked"};
    String[] tags = {"b", "i", "del", "mark"};
    List<String> indexer = new ArrayList<String>(Arrays.asList(tags));
    int index = 0;
    for (String x: styles) {
        if (s.startsWith(x)) {
            result = style(s, indexer.get(index));
            break;
        }
        index++;
    }
    if (result == null) result = s; //there was no formatting


    return result;

      //style method
      public String style(String text, String tag) {
    return "<" + tag + ">" + text + "</" + tag + ">";
}

This works but when i pass something like this to it: "Walking !deletedin the !boldstreet"

only it will turn !boldstreet into html tags. How can i make it turn everything like those into html tags?

Upvotes: 1

Views: 122

Answers (3)

Andy Turner
Andy Turner

Reputation: 140309

Try a pattern like:

Pattern pattern = Pattern.compile("!(bold|italic|deleted|marked)(.*?)\\b");

And then do the replacement something like:

Matcher matcher = pattern.matcher(s);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
  String tag = getTagFor(matcher.group(1));  // Implement lookup of tag from the bit immediately after the !
  String text = matcher.group(2);
  sb.appendReplacement(sb, String.format("<%s>%s</%s>", tag, text, tag));
}
matcher.appendTail(sb);

String result = sb.toString();

getTagFor might be something like:

String getTagFor(String code) {
  switch (code) {
    case "bold": return "b";
    case "italic": return "i";
    case "deleted": return "del";
    case "marked": return "mark";
    default: throw new IllegalArgumentException(code);
  }
}

or it could simply be a pre-built map. (A map might be better, because you can build the pattern by joining its keys, so you don't have the problem of keeping pattern and lookup in sync).

Upvotes: 2

cegredev
cegredev

Reputation: 1579

Not as fancy as using a regex, but gets the job done:

HashMap<String, String> tagsAndStyles = new HashMap<>();
tagsAndStyles.put("!deleted", "del");
tagsAndStyles.put("!bold", "b");
tagsAndStyles.put("!italic", "i");
tagsAndStyles.put("!marked", "mark");

String input = "Walking !deletedin the !boldstreet";
StringBuilder builder = new StringBuilder();

for (String segment : input.split(" ")) {
    for (String style : tagsAndStyles.keySet())
        if (segment.contains(style)) {
            String tag = tagsAndStyles.get(style);
            segment = "<" + tag + ">" + segment.substring(style.length()) + "</" + tag + ">";
            break;
        }

    builder.append(segment + " ");
}

builder.toString().trim();

Upvotes: 1

Sweeper
Sweeper

Reputation: 270850

Assuming that each !xxx applies only to the word after it, and "words" are space separated...

static String[] styles = {"!bold", "!italic", "!deleted", "!marked"};
static String[] tags = {"b", "i", "del", "mark"};

// this method styles *one* word only
public static String styleWord(String word) {
    for (int i = 0 ; i < styles.length ; i++) {
        if (word.startsWith(styles[i])) {
            String rest = word.substring(styles[i].length());
            String cleaned = styleWord(rest); // handles nested tags!
            return style(cleaned, tags[i]);
        }
    }
    return word; // no styles
}
public static String style(String text, String tag) {
    return "<" + tag + ">" + text + "</" + tag + ">";
}

// ...

String s = "Walking !deletedin the !boldstreet";

// splits the string into words
String[] words = s.split(" ");
// styles each word, and joins them all together again.
return Arrays.stream(words).map(EnclosingClass::styleWord).collect(Collectors.joining(" "));

Upvotes: 1

Related Questions