Regex on ;) smilie - regex

A minor inconvenience my users have found is that if they use a smilie such as >_> at the end of parentheses (kind of like this: >_>) then during processing it is run through htmlspecialchars(), making it >_>) - you can see the problem, I think. The ;) at the end is then replaced by the "Wink" smilie.
Can anyone give me a regex that will replace ;) with the smilie, but only if the ; is not the end of an HTML entity? (I'm sure it would involve a lookbehind but I can't seem to understand how to use them >_>)
Thank you!

Handling smileys like ;) is always a bit tricky - the way I would do it is transform it to the "canonical" :wink: before encoding HTML entities, and then changing only canonical-form :{smileyname}: smileys afterwards.

Like this: (?<!&[a-zA-Z0-9]+);\)
The (?>!...) is a zero-width assertion that will only allow the following construct to match text that isn't preceded by the ....

You should probably handle it along these lines, which sidesteps the issue of replacing replacements entirely:
Break the string apart wherever a smilie occurs, convert the smilies into tokens
HTML escape all the text nodes
Convert all the smilie tokens into their HTML tag equivalents
Glue everything back together
That's a bit non-trivial though. :)

Find: (&#?[a-z0-9]+;)\)
Replace: $0)
We're looking for:
Match the regular expression below and capture its match into backreference number 1 «(&#?[a-z0-9]+;)»
Match the character “&” literally «&»
Match the character “#” literally «#?»
Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
Match a single character present in the list below «[a-z0-9]+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
A character in the range between “a” and “z” «a-z»
A character in the range between “0” and “9” «0-9»
Match the character “;” literally «;»
Match the character “)” literally «\)»
Created with RegexBuddy

well if your intrested in a regex solution try this maybe
(?!t)([A-Za-z0-9]| );)

If it's in php (preg_replace you said ?), you can use preg_replace_callback :
preg_replace_callback('#(&[a-z0-9]+)?;\)#i', 'myFunction', 'myText');
in the "myFunction" function, you just have to check if you got some html entity in the capturing bracket.
function myFunction($matches) {
if(!empty($matches[1]) {
return $matches[0];
}
return '[Smilie]';
}

Related

Regex: Only capture if there is (are) characters between the searched characters

In my LaTeX work I need to do Regex search with \|(.*?)\| to capture |whatever| and replace it with \somecommand{$1}. But I do not want to capture || (That is, there is nothing between them.) How should I refine my regex search?
(By the way, what should my title be, so that it is useful for others?)
Change your regex to,
\|[^|]+\|
OR
\|.+\|
If you want to also capture pipes in between searched content
You have to change the asterix (which matches 0+ times) to a plus sign make the quantifier match at least 1 character.
\|(.+?)\|
^

Limiting RegEx to match only a string of 1-254 characters length

This is my RegEx:
"^[^\.]([\w-\!\#\$\%\&\'\*\+\-\/\=\`\{\|\}\~\?\^]+)([\.]{0,1})([\w-\!\#\$\%\&\'\*\+\-\/\=\`\{\|\}\~\?\^]+)[^\.]#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,6}|[0-9]{1,3})(\]?)$"
I need to match only strings less than 255 characters.
I've tried adding the word boundaries at the start of the RegEx but it fails:
"^(?=.{1,254})[^\.]([\w-\!\#\$\%\&\'\*\+\-\/\=\`\{\|\}\~\?\^]+)([\.]{0,1})([\w-\!\#\$\%\&\'\*\+\-\/\=\`\{\|\}\~\?\^]+)[^\.]#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,6}|[0-9]{1,3})(\]?)$"
You need the $ in the lookahead to make sure it's only up to 254. Otherwise, the lookahead will match even when there are more than 254.
(?=.{1,254}$)
Also, keep in mind that you can greatly simplify your regex because many characters that would usually need to be escaped do not need to when in a character class (square brackets).
"[\w-\!\#\$\%\&\'\*\+\-\/\=\`\{\|\}\~\?\^]"
is the same as this:
"[-\w!#$%&'*+/=`{|}~?^]"
Note that the dash must be first in the character class to be a literal dash, and the caret must not be first.
With some other simplifications, here is the complete string:
"^(?=.{1,254}$)[-\w!#$%&'*+/=`{|}~?^]+(\.[-\w!#$%&'*+/=`{|}~?^]+)*#((\d{1,3}\.){3}\d{1,3}|([-\w]+\.)+[a-zA-Z]{2,6})$"
Notes:
I removed the stipulation that the first char shouldn't be a period ([^.]) because the next character class doesn't match a period anyway, so it's redundant.
I removed many extraneous parens
I replaced [0-9] with \d
I replaced {0,1} with the shorthand "?"
After the # sign, it seemed that you were trying to match an IP address or text domain name, so I separated them more so it couldn't be a combination
I'm not sure what the optional square bracket at the end was for, so I removed it: "(]?)"
I tried it in Regex Hero, and it works. See if it works for you.
This depends on what language you are working in. In Python for example you can regex to split a text into separate strings, and then use len() to remove strings longer than the 255 characters you want
I think this post will help. It shows how to limit certain patterns but I am not sure how you would add it to the entire regex.

Regex for deleting characters before a certain character?

I'm very new at regex, and to be completely honest it confounds me. I need to grab the string after a certain character is reached in said string. I figured the easiest way to do this would be using regex, however like I said I'm very new to it. Can anyone help me with this or point me in the right direction?
For instance:
I need to check the string "23444:thisstring" and save "thisstring" to a new string.
If this is your string:
I'm very new at regex, and to be completely honest it confounds me
and you want to grab everything after the first "c", then this regular expression will work:
/c(.*)/s
It will return this match in the first matched group:
"ompletely honest it confounds me"
Try it at the regex tester here: regex tester
Explanation:
The c is the character you are looking for
.* (in combination with /s) matches everything left
(.*) captures what .* matched, making it available in $1 and returned in list context.
Regex for deleting characters before a certain character!
You can use lookahead like this
.*(?=x)
where x is a particular character or word or string.{using characters like .,$,^,*,+ have special meaning in regex so don't forget to escape when using it within x}
EDIT
for your sample string it would be
.*(?=thisstring)
.* matches 0 to many characters till thisisstring
Here is a one-line solution for matching everything after "before"
print $1."\n" if "beforeafter" =~ m/before(.*)/;
Edit:
While using lookbehind is possible, it's not required. Grouping provides an easier solution.
To get the string before : in your example, you have to use [^:][^:]*:\(.*\). Notice that you should have at least one [^:] followed by any number of [^:]s followed by an actual :, the character you are searching for.

How do you understand regular expressions that are written in one line?

This is a neat well documented regular expression, easy to understand, maintain and modify.
text = text.replace(/
( // Wrap whole match in $1
(
^[ \t]*>[ \t]? // '>' at the start of a line
.+\n // rest of the first line
(.+\n)* // subsequent consecutive lines
\n* // blanks
)+
)
/gm,
But how do you go about working with these?
text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
Is there a beautifier of some sort that makes sense of it and describes its functionality?
It's worth the effort to become adept at reading regexs in the one line form. Most of the time there are written this way
RegexBuddy will "translate" any regex for you. When fed your example regex, it outputs:
((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)
Options: ^ and $ match at line breaks
Match the regular expression below and capture its match into backreference number 1 «((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)»
Match the regular expression below and capture its match into backreference number 2 «(^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Note: You repeated the capturing group itself. The group will capture only the last iteration.
Put a capturing group around the repeated group to capture all iterations. «+»
Assert position at the beginning of a line (at beginning of the string or after a line break character) «^»
Match a single character present in the list below «[ \t]*»
Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
The character “ ” « »
A tab character «\t»
Match the character “>” literally «>»
Match a single character present in the list below «[ \t]?»
Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
The character “ ” « »
A tab character «\t»
Match any single character that is not a line break character «.+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Match a line feed character «\n»
Match the regular expression below and capture its match into backreference number 3 «(.+\n)*»
Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
Note: You repeated the capturing group itself. The group will capture only the last iteration.
Put a capturing group around the repeated group to capture all iterations. «*»
Match any single character that is not a line break character «.+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Match a line feed character «\n»
Match a line feed character «\n*»
Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
This does look rather intimidating in text form, but it's much more readable in HTML form (which can't be reproduced here) or in RegexBuddy itself. It also points out common gotchas (such as repeating capturing groups which is probably not wanted here).
I like expresso
After a while, I've gotten used to reading the things. There is not much to most regexes, and I recommend the site http://www.regular-expressions.info/ if you want to use them more often.
Regular expressions are just a way to express masks, etc. At the end it's just a "language" with its own syntax.
Comment every bit of your regular expression would be the same thing as comment every line of your project.
Of course it would help people who doesn't understand your code, but it's just useless if you (the developer) do understand the meaning of the regex.
For me, reading regular expressions is the same thing as reading code. If the expression is really complex an explanation below could be useful but most of the time it isn't necessary.

Why do I get successful but empty regex matches?

I'm searching the pattern (.*)\\1 on the text blabl with regexec(). I get successful but empty matches in regmatch_t structures. What exactly has been matched?
The regex .* can match successfully a string of zero characters, or the nothing that occurs between adjacent characters.
So your pattern is matching zero characters in the parens, and then matching zero characters immediately following that.
So if your regex was /f(.*)\1/ it would match the string "foo" between the 'f' and the first 'o'.
You might try using .+ instead of .*, as that matches one or more instead of zero or more. (Using .+ you should match the 'oo' in 'foo')
\1 is the backreference typically used for replacement later or when trying to further refine your regex by getting a match within a match. You should just use (.*), this will give you the results you want and will automatically be given the backreference number 1. I'm no regex expert but these are my thoughts based on my limited knowledge.
As an aside, I always revert back to RegexBuddy when trying to see what's really happening.
\1 is the "re-match" instruction. The question is, do you want to re-match immediately (e.g., BLABLA)
/(.+)\1/
or later (e.g., BLAahemBLA)
/(.+).*\1/