I am in iOS but pretty much any language will translate.
I am trying to write a regular expression to match a root directory:
ie:
First/ should match
First/file.txt should not match
First/next should not match
First/next/file.txt should not match
So I think the logic should be start at beginning of line match any character except "/" then match "/" only once and that one time should be at the end of the string.
I have:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[^\\/]*\\/$" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger matches = [regex numberOfMatchesInString:info.name options:NSRegularExpressionCaseInsensitive range:NSMakeRange(0, [info.name length])];
if (matches > 0) {
NSLog(#"match");
} else {
NSLog(#"not a match");
}
But its not matching like it should.
Thinking
[^\\/]*
will match all characters that are not "/"
Then
\\/$
will match a "/" that is at the end of the string.
Where am I going wrong?
The regular expression would be:
^[^/]*/$
This ensures the string ends with a slash and it can contain 0 or more non-slash characters before it.
Another solution (without regular expression) would be this:
NSString *name = ... // some path
if (name.length && [name rangeOfString:#"/"].location == name.length - 1) {
// root directory
}
Related
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.
I've a certain regex pattern to check against.
Valid result is is only Hebrew language, letters, marks etc.
//////////Regex//////////
static NSString *const HEBREW_NUMBERS_NON_NUMERIC_CHAR = #"([\u0590-\u05FF]*|[0-9]*|[\\s]*|[.-:;,?!/&*()+=_'\"]*)+";
+ (BOOL)hasValidOpenLine:(NSString *)openLine
{
if (openLine.length >= MIN_NUMBER_OF_CHARACTERS_IN_OPEN_LINE || openLine.length <= MAX_NUMBER_OF_CHARACTERS_IN_OPEN_LINE) {
NSError *errorRegex;
NSRegularExpression *regexOpenLine = [[NSRegularExpression alloc] initWithPattern:HEBREW_NUMBERS_NON_NUMERIC_CHAR
options:0
error:&errorRegex];
NSRange range = NSMakeRange(0, openLine.length);
if ([regexOpenLine numberOfMatchesInString:openLine options:0 range:range] > 0) {
return YES;
}
}
return NO;
}
But no matter what I type, it always return me YES even for only English string.
There may be two things going wrong here, depending on your test string. First off, the stars in your regex allow for empty matches against strings which would otherwise not match, which is why your regex might match English strings — matching your regex on #"Hello, world!" returns {0, 0}, a range whose location is not NSNotFound, but whose length is zero.
The other issue is that you're not anchoring your search. This will allow the regex to match against singular characters in strings that would otherwise not match (e.g. the , in #"Hello, world!"). What you need to do is anchor the regex so that the whole string has to match, or else the regex rejects it.
Your modified code can look something like this:
static NSString *const HEBREW_NUMBERS_NON_NUMERIC_CHAR = #"([\u0590-\u05FF]|[0-9]|[\\s]|[.-:;,?!/&*()+=_'\"])+";
+ (BOOL)hasValidOpenLine:(NSString *)openLine
{
if (openLine.length >= MIN_NUMBER_OF_CHARACTERS_IN_OPEN_LINE || openLine.length <= MAX_NUMBER_OF_CHARACTERS_IN_OPEN_LINE) {
NSError *errorRegex;
NSRegularExpression *regexOpenLine = [[NSRegularExpression alloc] initWithPattern:HEBREW_NUMBERS_NON_NUMERIC_CHAR
options:0
error:&errorRegex];
if ([regexOpenLine numberOfMatchesInString:openLine options:NSMatchingAnchored range:NSMakeRange(0, openLine.length)] > 0) {
return YES;
}
}
return NO;
}
This will now match against strings like #"שלום!", and not strings like #"Hello, world!" or #"Hello: היי", which is what I assume you're going for.
In the future, if you're looking to debug regexes, use -[NSRegularExpression rangeOfFirstMatchInString:options:range:] or -[NSRegularExpression enumerateMatchesInString:options:range:usingBlock:]; they can help you find matches that may cause your regex to accept unnecessarily.
I can't find a regular expression having balanced tags, one for opening and one for closing.
Tags must enclose multi lines text; and tags are dynamic, not defined at compile time
I can't match the closing tag corresponding to the opening tag, for instance {{home}} -> {{/home}} and {{hello}} -> {{/hello}}; it match {{home}} to {{/hello}}
Any help will be greatly appreciated
Any help will be greatly appreciated
gregoire
ps : I commented non working regexp
NSString * string;
NSError* error = nil;
NSRegularExpression* regex;
NSArray* matches;
string =
#" The {{demo}}following tables describe the {{/demo}}character expressions"
" used by the regular expression to match patterns within "
" a string,{{home}} the pattern operators that specify how many"
" times a pattern is matched and additional matching"
" restrictions, and the last {{/home}}table specifies flags"
" that can be included in the regular ";
regex = [NSRegularExpression regularExpressionWithPattern:
#"\\{\\{demo\\}\\}"
"(.*)?"
"\\{\\{(//|/demo)\\}\\}"
options:NSRegularExpressionDotMatchesLineSeparators
error:&error];
// regex = [NSRegularExpression regularExpressionWithPattern:
// #"\\{\\{.*\\}\\}"
// "(.*)?"
// "\\{\\{(//|/.*)\\}\\}"
// options:NSRegularExpressionDotMatchesLineSeparators
// error:&error];
matches = [regex matchesInString:string
options:NSRegularExpressionDotMatchesLineSeparators
range:NSMakeRange(0, [string length])];
for ( NSTextCheckingResult* match in matches )
{
NSLog(#"### %# ###", [string substringWithRange:[match range]]);
}
You can use this pattern
\{\{([^/]*?)\}\}(.*?)\{\{(/\1|//)\}\}
------- ---- --------
| | |->matches closing tag having value same as group 1 or //
| |->content in group 2
|->matches the opening tag value and captures it in group1
I am looking for a regular expression to match the following -100..100:0.01. The meaning of this expression is that the value can increment by 0.01 and should be in the range -100 to 100.
Any help ?
You could use NSRegularExpression instead. It does support \b, btw, though you have to escape it in the string:
NSString *regex = #"\\b-?1?[0-9]{2}(\\.[0-9]{1,2})?\\b";
Though, I think \\W would be a better idea, since \\b messes up detecting the negative sign on the number.
A hopefully better example:
NSString *string = <...your source string...>;
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"\\W-?1?[0-9]{2}(\\.[0-9]{1,2})?\\W"
options:0
error:&error];
NSRange range = [regex rangeOfFirstMatchInString:string
options:0
range:NSMakeRange(0, [string length])];
NSString *result = [string substringWithRange:range];
I hope this helps. :)
EDIT: fixed based on the below comment.
(\b|-)(100(\.0+)?|[1-9]?[0-9](\.[0-9]{1,2})?\b
Explanation:
(\b|-) # word boundary or -
( # Either match
100 # 100
(\.0+)? # optionally followed by .00....
| # or match
[1-9]? # optional "tens" digit
[0-9] # required "ones" digit
( # Try to match
\. # a dot
[0-9]{1,2}# followed by one or two digits
)? # all of this optionally
) # End of alternation
\b # Match a word boundary (make sure the number stops here).
Why do you want to use a regular expression? Why not just do something like (in pseudocode):
is number between -100 and 100?
yes:
multiply number by 100
is number an integer?
yes: you win!
no: you don't win!
no:
you don't win!
if(val>= -100 && val <= 100)
{
NSString* valregex = #"^[+|-]*[0-9]*.[0-9]{1,2}";
NSPredicate* valtest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", valregex];
ret = [valtest evaluateWithObject:txtLastname.text];
if (!ret)
{
[alert setMessage:NSLocalizedString(#"More than 2 decimals", #"")];
[alert show];
}
}
works fine.. Thnx for the efforts guys !
I am so confused about the regex methods. My requirement is to validate a phone number that may contains + symbol in its prefix. Then all the charactors should be numerals only. For this, how can i create a regular expression in objective c.
I'm late answering, but I found an interesting solution when I recently have had the same problem. It uses the built-in cocoa methods instead of custom regex.
- (BOOL)validatePhoneNumberWithString:(NSString *)string {
if (nil == string || ([string length] < 2 ) )
return NO;
NSError *error;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber error:&error];
NSArray *matches = [detector matchesInString:string options:0 range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypePhoneNumber) {
NSString *phoneNumber = [match phoneNumber];
if ([string isEqualToString:phoneNumber]) {
return YES;
}
}
}
return NO;
}
I wouldn't say this is a definitive answer but it should give you a start.
^\x2b[0-9]+
Will match any string that starts with a '+' and then any amount of numbers greater than 0.
For instance:
+441312002000 - Full phone number matched.
+4413120c2000 - +4413120 is matched.
++441312002000 - No match
441312002000 - No Match
If there are further constraints on length etc then specifiy and I can update the regex. I agree with other poster about using RegexKitLite.
Use RegexKitLite, check the following http://regexkit.sourceforge.net/RegexKitLite/
^\+?[0-9]*$
should do:
^ # start of string
\+? # match zero or one + characters
[0-9]* # match any number of digits
$ # end of string
To use the regex in a string, you'll need to double the backslashes: #"^\\+?[0-9]*$" should work according to other regex examples I've seen, but I don't know Objective-C and may be wrong about this.
This post nicely explains the regex -- http://blog.stevenlevithan.com/archives/validate-phone-number. You have to use "\" instead of "\" to prevent the Objective C preprocessor from interpreting regex escape codes as character string escape codes.
Here is the NSString you would use for the requested match
NSString *northAmRegexWithOptionalLeadingOne = #"^(?:\\+?1[-. ]?)?\\(?([2-9][0-8][0-9])\\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$";
+*[0-9]{length of phone}. Should work.