Coloring Text within $ - NSString - ios

pattern = #"(\\$.*?\\$)";
regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
matches = [regex matchesInString:self options:0 range: searchedRange];
for (NSTextCheckingResult* match in matches) {
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:[match range]];
}
I'm using the above code to color text inbetween two dollar signs. So the hello world text in the following string would be colored blue, with the dollar signs removed:
#"This won't be blue. $hello world$. This won't be blue";
Now, however, I want a single dollar sign to not be colored blue. I only want the pattern to match when the first dollar sign is succeeded by a character in a-zA-Z0-9 and likewise the second dollar sign should be preceded by a character in a-zA-Z0-9. How can I do this?

Move the capturing group a bit after the first $ and before the last $, and use matchAtIndex:1 to only get Group 1 value:
pattern = #"\\$([A-Za-z0-9].*?)(?<=[A-Za-z0-9])\\$";
^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
And
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:[match matchAtIndex:1]];
Pattern details:
\\$ - a literal $
([A-Za-z0-9].*?) - a letter or digit followed with 0+ any chars but a newline as few as possible upto the first
(?<=[A-Za-z0-9])\\$ - $ that is preceded with a letter or digit
If you only need to make sure a digit or letter appears after the first $, use
pattern = #"\\$\\b(?!_)(.*?)\\$";
Where the first $ can be followed with letters or digits, but not _.

You probably just need to adjust your regular expression a little.
A really good resource for this is http://regexr.com/ because it lets you try out new expressions live.
In this specific case you probably want:
pattern = #"(\\$.+\\$)";
The difference between * and + is that + requires at least 1 character. Also the ? was not doing anything because the * by default makes something optional.

I believe this does what I want pattern = #"(\\$[a-zA-Z0-9]{1}.*\\$)";
Thanks to Tristan for the resource

Related

Regex to capture all text before { character - Objective C

How would I write a regex to capture all text before the { character but on the same line?
I tried something like the following:
pattern = #"(\{)";
regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
matches = [regex matchesInString:self options:0 range: searchedRange];
for (NSTextCheckingResult* match in matches) {
[string addAttribute:NSForegroundColorAttributeName value: [UIColor colorFromHexString:#"#C41A16"] range:[match range]];
}
I'm trying to style the following CSS code such that p is colored and a is colored:
p {
color: blue;
}
a {
color: red;
}
How would I write a regex to capture all text before the { character but on the same line?
Use
pattern = #"(?m)^([^{\r\n]*)\\{";
This will only match and capture a part of the line from the start till the first { and will match the { itself. The [^{\r\n] negated character class only matches a character other than {, CR and LF.
See the regex demo
To match the text before the { only (excluding {) you may use a lookahead:
pattern = #"(?m)^[^{\r\n]*(?=\\{)";
^^^^^^^
See another regex demo
And finally, you may also "trim" the match with the help of a lazy *? quantifier and the * (zero or more spaces) inside the lookahead:
pattern = #"(?m)^[^{\r\n]*?(?= *\\{)";
Yet another demo

One uppercase letter validation regex

I am working on a regex validation for an alphanumeric character with a length of 4 but contains only one Uppercase letter.
This is the code I have:
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:#"(?=.*[0-9])(?=.*[A-Z])[a-zA-Z0-9]{4}" options:NSRegularExpressionCaseInsensitive error:&error];
However, it does not perform the check correctly. How can I do it?
Change your pattern like this,
#"^(?=.*[0-9])(?=[^A-Z]*[A-Z][^A-Z]*$)[a-zA-Z0-9]{4}$"
I think this would be enough for you
#"^(?=.*\\d)(?=.*[A-Z]).{4}$"
Or if you want to give minimum and maximum length then use below snippet
#"^(?=.*\\d)(?=.*[A-Z]).{4,15}$"
Here 4 would be the minimum length and 15 would be maximum length for your string
If you need to differentiate upper- and lowercase letters, you need to remove NSRegularExpressionCaseInsensitive option. It removes the differentiation between the lower and upper case.
Once you remove it, the following regex (if you need to support Unicode letters):
#"\\A(?=\\D*\\d)(?=\\P{Lu}*\\p{Lu}\\P{Lu}*\\z)[\\p{L}\\d]{4}\\z"
Or just ASCII:
#"\\A(?=\\D*\\d)(?=[^A-Z]*[A-Z][^A-Z]*\\z)[A-Za-z\\d]{4}\\z"
See another regex demo
NSRegularExpression *expression = [
NSRegularExpression regularExpressionWithPattern:#"\\A(?=\\D*\\d)(?=[^A-Z]*[A-Z][^A-Z]*\\z)[A-Za-z\\d]{4}\\z"
options:0
error:&error];
Regex breakdown:
\A - unambigous start of string
(?=\D*\d) - check if there is at least 1 digit after 0 or more non-digits (\D*)
(?=\P{Lu}*\p{Lu}\P{Lu}*\z) - check if there is ONLY 1 uppercase letter (\p{L}) in-between 0 or more any characters other than uppercase letters (\P{Lu})
[\p{L}\d]{4} - exactly 4 characters that are either a letter (lower- or uppercase) or a digit.
\z - match unambigous end of string.
IDEONE demo resulting in "yes":
NSString * s = #"e3Df";
NSString * rx = #"\\A(?=\\D*\\d)(?=[^A-Z]*[A-Z][^A-Z]*\\z)[A-Za-z\\d]{4}\\z";
NSPredicate * predicat = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", rx];
if ([predicat evaluateWithObject:s]) {
NSLog (#"yes");
}
else {
NSLog (#"no");
}

NSMutable String: How do I get the index of multiple spaces in a string?

I want to find the index of the 8th occurrence of " " so that I could split my string there. However all I can find is this line of code that gives me an array of all the occurrences of " ". Is there a function I can call that would give me this information?
int numberOfOccurences = [[myListString componentsSeparatedByString:#" "] count];
Edit 1: So far this is the solution I came up with:
if(numberOfOccurences > 8)
{
//find index of place where you want to split by picking an
//arbitrary number and finding the first white space
int index = (int)[[myListString substringFromIndex:45] rangeOfString:#" "].location;
NSLog(#"Index: %i", index);
//make substring
NSString *substringList1 = [myListString substringToIndex:(45+index)];
NSString *substringList2 = [myListString substringFromIndex:(45+index)];
}
There is no method to find the 8th space, but there are the building blocks you need.
The NSString method rangeOfString:options:range: will find the first occurrence of its first argument within the range specified by its third argument, it returns a range for the match. You simply start with the third argument being the whole string and then iterate reducing the range to search using the previous result.
If you are actually looking for white space and not simply a space you might consider the similar rangeOfCharactersFromSet methods.
If you don't really want the eighth space, but are trying to break a string at a given length, you can look at componentsSeparatedByString/componentsSeparatedByCharactersInSet and then reassemble the resultant “words" into strings of the appropriate length. You might also want to look at NSScanner.
HTH
With the explicit assumption that you are looking for the eighth space (and possibly needing to adjust the regex a little depending on character set), you could use a regular expression:
NSRegularExpression *exp = [NSRegularExpression regularExpressionWithPattern:#"^([^ ]* ){8}+"
options:0
error:NULL];
NSRange result = [exp rangeOfFirstMatchInString:input options:0 range:inputRange];
If result.location != NSNotFound then result.length gives you the index on which to split.

How to replace strings using regex in objective C?

I have a string that sometimes contains strings like: #"[id123123|Some Name]"
What I have to do, is to simply replace it to "Some Name"
For example I have string: Some text lalala blabla [id123|Some Name] bla bla bla
And I need to get: Some text lalala blabla Some Name bla bla bla
The question is how to? My mind tells me that I can do this with NSRegularExpression
Look into stringByReplacingOccurrencesOfString:withString:options:range:. The options: allow the search string to be a regular expression pattern.
Not an Objective C person, but judging from this previous SO post, you could use a regex like so:
NSString *regexToReplaceRawLinks = #"\\[.+?\\|(.+?)\\]";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexToReplaceRawLinks
options:NSRegularExpressionCaseInsensitive
error:&error];
NSString *string = #"[id123|Some Name]";
NSString *modifiedString = [regex stringByReplacingMatchesInString:string
options:0
range:NSMakeRange(0, [string length])
withTemplate:#"$1"];
This should match the string you are using and place the name in a group. You then replace the entire string [id123|Some Name] with Some Name.
Regex101
(\[[^|]+|([^\]]+]))
Description
\[ matches the character [ literally
[^|]+ match a single character not present in the list below
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
| the literal character |
\| matches the character | literally
1st Capturing group ([^\]]+])
[^\]]+ match a single character not present in the list below
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
\] matches the character ] literally
] matches the character ] literally
In capture group 1 is the thing you want to replace with what is in capture group 2. enjoy.

iOS - NSString regex match

I have a string for example:
NSString *str = #"Strängnäs"
Then I use a method for replace scandinavian letters with *, so it would be:
NSString *strReplaced = #"Str*ngn*s"
I need a function to match str with strReplaced. In other words, the * should be treated as any character ( * should match with any character).
How can I achieve this?
Strängnäs should be equal to Str*ngn*s
EDIT:
Maybe I wasn't clear enough. I want * to be treated as any character. So when doing [#"Strängnäs" isEqualToString:#"Str*ngn*s"] it should return YES
I think the following regex pattern will match all non-ASCII text considering that Scandinavian letters are not ASCII:
[^ -~]
Treat each line separately to avoid matching the newline character and replace the matches with *.
Demo: https://regex101.com/r/dI6zN5/1
Edit:
Here's an optimized pattern based on the above one:
[^\000-~]
Demo: https://regex101.com/r/lO0bE9/1
Edit 1: As per your comment, you need a UDF (User defined function) that:
takes in the Scandinavian string
converts all of its Scandinavian letters to *
takes in the string with the asterisks
compares the two strings
return True if the two strings match, else false.
You can then use the UDF like CompareString(ScanStr,AsteriskStr).
I have created a code example using the regex posted by JLILI Amen
Code
NSString *string = #"Strängnäs";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[^ -~]" options:NSRegularExpressionCaseInsensitive error:&error];
NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:#"*"];
NSLog(#"%#", modifiedString);
Output
Str*ngn*s
Not sure exactly what you are after, but maybe this will help.
The regular expression pattern which matches anything is. (dot), so you can create a pattern from your strReplaced by replacing the *'s with .'s:
NSString *pattern = [strReplaced stringByReplacingOccurencesOfString:#"*" withString:"."];
Now using NSRegularExpression you can construct a regular expression from pattern and then see if str matches it - see the documentation for the required methods.

Resources