Currently working on a web server with bottle and trying to implement a function that accepts a message and converts it to HTML suitable for display. There is the limitation of
Any hashtags in the text ('#' followed by a sequence of letters, numbers or periods)
are enclosed by a <strong class='hashtag'> tag.
Eg. <strong class='hashtag'>#whatever</strong>
The part i have an issue with is when there is more than one hashtag in a block of text, as using regex allows me to find the certain hashtag blocks but re.sub replaces all hashtags with the one value given. This is what i have:
def post_to_html(content):
if (re.search(r'#[\d\w\.]*', content) is not None):
hold = re.search(r'#[\d\w\.]*', content).group(0)
repltxt = "<strong class='hashtag'>{0}</strong>".format(hold)
hold = re.sub(r'#[\d\w\.]*', repltxt, content)
content = hold
Which when given:
"#whatever you #want"
Outputs:
<strong class='hashtag'>#whatever</strong> you <strong class='hashtag'>#whatever</strong>
You can actually fix your problem with only one usage of the re.sub method and then you don't have to hold any variables and so on:
fixed_content = re.sub(r"(#[\d\w\.]+)", r"<strong class='hashtag'>\1</strong>", content)
You do need to change your regex a bit:
+ instead of the * to make sure you don't match any lonely # in the content\g<1> or \1.The \g<n> and \n are what we call "backreferences" in the regular expressions world. You can have multiple capturing groups and multiple backreferences as well - \1, \2, \n. According to this definition:
Backreferences match the same text as previously matched by a capturing group
You can use backreferences every time you need to reuse its capturing group's matched content. In your case, you want to save the actual hashtag for later usage, so instead of having additional temp variables, you can just use the backreference \n.
Have a look at a simple example. Let's say you want a regex to replace HTML <strong> tags with <b> and you come up with the following regex:
> pattern = re.compile(r"<strong>.+?</strong>")
This will match everything between a <strong> and </strong>, tags included. However, you want to reuse the actual element in between those tags. So let's make a capturing group by surrounding the element matching part with brackets:
> pattern = re.compile(r"<strong>(.+?)</strong>")
Now, your capturing group's content can be reused with \1. If we try to use it with an example text this is what happens:
> pattern.sub(r"<b>\1</b>", "some <strong>text</strong> example")
'some <b>text</b> example'
Backreferences are super useful when dealing with replacements and complex regexes. You can read a bit more about them here and also check Python's documentation on how to use it in a more advanced way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With