How to get regex to grab all letters from an objective c string? - objective-c

I'm trying to get the following regular expression to grab only the letters from an alpha-numeric character input box, however it's always returning the full string, and not any of the A-Z letters.
What am I doing wrong?
It needs to grab all the letters only. No weird characters and no numbers, just A-Z and put it into a string for me to use later on.
// A default follows
NSString *TAXCODE = txtTaxCode.text;
// Setup default for taxcode
if ([TAXCODE length] ==0)
{
TAXCODE = #"647L";
}
NSError *error = NULL;
NSRegularExpression *regex;
regex = [NSRegularExpression regularExpressionWithPattern:#"/[^A-Z]/gi"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSLog(#"TAXCODE = %#", TAXCODE);
NSLog(#"TAXCODE.length = %d", [TAXCODE length]);
NSLog(#"STC (before regex) = %#", STC);
STC = [regex stringByReplacingMatchesInString:TAXCODE
options:0
range:NSMakeRange(0, [TAXCODE length])
withTemplate:#""];
NSLog(#"STC (after regex) = %#", STC);
My debug output is as follows:
TAXCODE = 647L
TAXCODE.length = 4
STC (before regex) =
STC (after regex) = 647L

If you only ever going to have letters on one end then you could use.
NSString *TAXCODE =#"647L";
NSString *newcode = [TAXCODE stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];
If intermixed letters then you can get an Array that you can then play with.
NSString *TAXCODE =#"L6J47L";
NSArray *newcodeArray = [TAXCODE componentsSeparatedByCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];

I think you need to drop the perl syntax on the regexp. Use #"[^A-Z]" as the match string.

Related

How to display persian script through unicode

Someone please help me displaying this string in persian script: "\u0622\u062f\u0631\u0633 \u0627\u06cc\u0645\u06cc\u0644"
I have tried using
NSData *data = [yourtext dataUsingEncoding:NSUTF8StringEncoding];
NSString *decodevalue = [[NSString alloc] initWithData:dataencoding:NSNonLossyASCIIStringEncoding];
and this gets returned: u0622u062fu0631u0633 u0627u06ccu0645u06ccu0644
I want the same solution for objective C: https://www.codeproject.com/Questions/714169/Conversion-from-Unicode-to-Original-format-csharp
I assume that your input string has backslash-escaped codes (as if it was in a source code file verbatim), and you want to parse the escape sequences it into a unicode string, and also want to preserve the unescaped characters as they are.
This is what I've came up with:
NSError *badRegexError;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(\\\\u([a-f0-9]{4})|.)" options:0 error:&badRegexError];
if (badRegexError) {
NSLog(#"bad regex: %#", badRegexError);
return;
}
NSString *input = #"\\u0622\\u062f\\u0631\\u0633 123 test -_- \\u0627\\u06cc\\u0645\\u06cc\\u0644";
NSMutableString *output = [NSMutableString new];
[regex enumerateMatchesInString:input options:0 range:NSMakeRange(0, input.length)
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
{
NSRange codeRange = [result rangeAtIndex:2];
if (codeRange.location != NSNotFound) {
NSString *codeStr = [input substringWithRange:codeRange];
NSScanner *scanner = [NSScanner scannerWithString:codeStr];
unsigned int code;
if ([scanner scanHexInt:&code]) {
unichar c = (unichar)code;
[output appendString:[NSString stringWithCharacters:&c length:1]];
}
} else {
[output appendString:[input substringWithRange:result.range]];
}
}];
NSLog(#" actual: %#", output);
NSLog(#"expected: %#", #"\u0622\u062f\u0631\u0633 123 test -_- \u0627\u06cc\u0645\u06cc\u0644");
Explanation
This is using a regex that finds blocks of 6 characters like \uXXXX, for example \u062f. It extracts the code as a string like 062f, and then uses NSScanner.scanHexInt to convert it to a number. It assumes that this number is a valid unichar, and builds a string from it.
Note \\\\ in the regex, because first the objc compiler one layer of slashes, and it becomes \\, and then the regex compiler removes the 2nd layer of slashes and it becomes \ which is used for exact matching. If you have just "u0622u062f..." (without slashes), try removing \\\\ from the regex.
The second part of the regex (|.) treats non-escaped characters as is.
Caveats
You also might want to make the matching case insensitive by setting proper regex options.
This doesn't handle invalid character codes.
This is not the most performant solution, and you'd better use a proper parsing library to do this at scale.
Related docs and links
https://developer.apple.com/documentation/foundation/nsregularexpression?language=objc
https://developer.apple.com/documentation/foundation/nsregularexpression/1409687-enumeratematchesinstring?language=objc
How do you use NSRegularExpression's replacementStringForResult:inString:offset:template:
https://developer.apple.com/documentation/foundation/nstextcheckingresult?language=objc
xcode UTF-8 literals
Objective-C parse hex string to integer
just copy and paste this phrase to python shell and press "Enter" you will see this phrase in Farsi or Persian language. the result is: ایمیل آدرس

Objective C - Split string into array

How would I do this? I'm new to Objective-C but I can't find anything that would help me do this.
NSArray *splitLine = [currentLine componentsSeparatedByString:#":%#",notNumber];
Where notNumber is a string that represents anything that isn't a number. So I want to separate a string where there are colons separated by strings that aren't numbers. (I want to avoid splitting at times i.e. 3:00pm, but split at iCal parameters like DESCRIPTION: and LOCATION:.)
You can do this in several steps, like this. I have not compiled this code, but it should at least give you an idea of what to do.
1) Create a regex object to match your separators:
NSString *regexString = #"DESCRIPTION:\s|LOCATION:\s"; // or whatever makes sense for your scenario
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:regexString
options:NSRegularExpressionCaseInsensitive
error:nil];
2) Replace all the different separators matching your regex with just one separator:
NSRange range = NSMakeRange(0, string.length);
NSString *string2 = [regex stringByReplacingMatchesInString:string
options:0
range:range
withTemplate:#"SEPARATOR"];
3) Split the string!
NSArray *elements = [string2 componentsSeparatedByString:#"SEPARATOR"];
Shortest solution for splitting string.
NSString *str = #"Please split me to form array of words";
NSArray *wordsArray = [str componentsSeparatedByString:#" "];
You can use regular expressions!
Using the pattern (I believe this is the core of your question):
pattern = #"(?<=[^0-9]):(?=[^0-9])"
This pattern will only match ':' symbols not surrounded by numbers.
Then replace with a dummy value that won't show in your data
dummy = #"NEVERSEETHIS"
NSRegularExpressions *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
NSRange range = NSMakeRange(0, [string length])
NSString *modified= [regex replaceMatchesInString:yourString options:0 range:range withTemplate:dummy];
and finally, split
return [modified componentsSeparatedByString:dummy];

NSRegularExpression get only the regex

i have a problem and i don't undestand how to do this ( after 6hours or googling)
i'have a string named "filename" containt this text :"Aachen-Merzbrück EDKA\r\r\nVerkehr"
i want to use regex to only get this part "Aachen-Merzbrück EDKA" but i cant....
here my code :
NSString *expression = #"\\w+\\s[A-Z]{4}";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:&error];
NSString *noAirportString = [regex stringByReplacingMatchesInString:filename options:0 range:NSMakeRange(0, [filename length]) withTemplate:#""];
EDIT :
this one work good :
\S+\s+[A-Z]{4}
but now, how to get only this "Aachen-Merzbrück" EDKA from "Aachen-Merzbrück EDKA\r\r\nVerkehr"
my regex with NSRegularExpression return me the same string ....
A couple of issues in your question:
No need to match city name characters - there are always weird ones around (hyphens, apostrophes, etc.) You can just match the first "line" in your text with a test for the ICAO code as an extra security.
Using stringByReplacingMatchesInString: you actually remove the airport name (and ICAO code) that you want keep.
stringByReplacingMatchesInString: is a hacky (because it deletes things, so you need to make your regexes "negative") shortcut that sometimes works (I use it myself) but which risks confusing things - and future readers.
Having said that, a few changes will fix it:
NSString *filename = #"Aachen-Merzbrück EDKA\r\r\nVerkehr";
// Match anything from the beginning of the line up to a space and 4 upper case letters.
NSString *expression = #"^.+\\s[A-Z]{4}$";
NSError *error = NULL;
//Make sure ^ and $ match line endings,
//and make it case sensitive (the default) to explicitly
//match the 4 upper case characters of the ICAO code
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionAnchorsMatchLines error:&error];
NSArray *matches = [regex matchesInString:filename
options:0
range:NSMakeRange(0, [filename length])];
// Check that there _is_ a match before you continue
if (matches.count == 0) {
// Error
}
NSRange airportNameRange = [[matches objectAtIndex: 0] range];
NSString *airportString = [filename substringWithRange: airportNameRange];
Thanks it's good working, but i use this one, it's work better in my case :
NSString *expression = #"\\S+\\s+[A-Z]{4}";

Objective c comparing strings multiple words

Hi I'm looking to compare 2 strings using objective c. One string is a single word and the other will be one or more words. How can I cheeck for a match at word level? I.e if any word from the multiple word string matches my single word string return a 1 else return a 0 ? Any help much appreciated.
You might be tempted to use -[NSString rangeOfString:]:
if ([multipleWords rangeOfString:singleWord].location != NSNotFound)
return YES;
return NO;
But it's imperfect. You could have "returning" in multipleWords and singleWord could be "return", giving you a false positive.
So instead we must use NSRegularExpression.
NSString *single = #"returning";
NSString *multiple = #"a man is returning home";
NSString *pattern = [NSString stringWithFormat:#"\\b%#\\b",single];
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionCaseInsensitive
error:&error];
NSRange range = NSMakeRange(0, multiple.length);
NSUInteger matched = [regex numberOfMatchesInString:multiple options:0 range:range];
NSLog(#"number of matched = %ld", matched);
You can use NSString's rangeOfString method:
NSRange range = [multiWordString rangeOfString:oneWordString];
if (range.location == NSNotFound)
return 0;
else
return 1;
The above code will return 1 if you are searching for "WAR" inside the longer "I AM AWARE". Maybe you're looking for entire word match.
In that case you should split the long string into an array of single words using...
NSArray *singleWords = [multiWordString componentsSeparatedByString: #" "];
Then parse the array to find the oneWordString
You can split up words in a string into an array using [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]. You can then check each word in the array to see if it matches the single word being searched. It's not the most efficient way, but it could work for your needs.

Objective-C NSString character substitution

I have a NSString category I am working on to perform character substitution similar to PHP's strtr. This method takes a string and replaces every occurrence of each character in fromString and replaces it with the character in toString with the same index. I have a working method but it is not very performant and would like to make it quicker and able to handle megabytes of data.
Edit (for clarity):
stringByReplacingOccurrencesOfString:withString:options:range: will not work. I have to take a string like "ABC" and after replacing "A" with "B" and "B" with "A" end up with "BAC". Successive invocations of stringByReplacingOccurrencesOfString:withString:options:range: would make a string like "AAC" which would be incorrect.
Suggestions would be great, sample code would be even better!
Code:
- (NSString *)stringBySubstitutingCharactersFromString:(NSString *)fromString
toString:(NSString *)toString;
{
NSMutableString *substitutedString = [self mutableCopy];
NSString *aCharacterString;
NSUInteger characterIndex
, stringLength = substitutedString.length;
for (NSUInteger i = 0; i < stringLength; ++i) {
aCharacterString = [NSString stringWithFormat: #"%C", [substitutedString characterAtIndex:i]];
characterIndex = [fromString rangeOfString:aCharacterString].location;
if (characterIndex == NSNotFound) continue;
[substitutedString replaceCharactersInRange:NSMakeRange(i, 1)
withString:[NSString stringWithFormat:#"%C", [toString characterAtIndex:characterIndex]]];
}
return substitutedString;
}
Also this code is executed after every change to text in a text view. It is passed the entire string every time. I know that there is a better way to do it, but I do not know how. Any suggestions for this would be most certainly appreciated!
You can make that kind of string substitution with NSRegularExpression either modifying an mutable string or creating a new immutable string. It will work with any two strings to substitute (even if they are more than one symbol) but you will need to escape any character that means something in a regular expression (like \ [ ( . * ? + etc).
The pattern finds either of the two substrings with the optional "anything" between and than replaces them with the two substrings with each other preserving the optional string between them.
// These string can be of any length
NSString *firstString = #"Axa";
NSString *secondString = #"By";
// Escaping of characters used in regular expressions has NOT been done here
NSString *pattern = [NSString stringWithFormat:#"(%#|%#)(.*?)(%#|%#)", firstString, secondString, firstString, secondString];
NSString *string = #"AxaByCAxaCBy";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionCaseInsensitive
error:&error];
if (error) {
// Insert error handling here...
}
NSString *modifiedString = [regex stringByReplacingMatchesInString:string
options:0
range:NSMakeRange(0, [string length])
withTemplate:#"$3$2$1"];
NSLog(#"Before:\t%#", string); // AxaByCAxaCBy
NSLog(#"After: \t%#", modifiedString); // ByAxaCByCAxa