Extract Contents of Anchor Tag - objective-c

What I'm trying to do is extract the contents of a an anchor tag being stored in an NSString.
If for example I have a string with the following:
Amazon <b>Kindle</b>: Welcome
How would I go about extracting the contents of the anchor tag so that I would have the following:
https://kindle.amazon.com/&sa=U&ei=GdiWT5uCEI6BhQfihoTzDQ&ved=0CCUQFjAB&usg=AFQjCNEoRolsgoynLNS0H60VWz-9EaQdtw
Any help would be greatly appreciated!
I'm completely stumped, whereas this should be quite simple? The answer posted below keeps returning null.

If you can require Lion, then you can use NSRegularExpression.
NSString* stringToSearch = #"Amazon <b>Kindle</b>: Welcome";
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"href\\s*=\\s*\"\\/url\\?q=([^\"]*)\""
options:NSRegularExpressionCaseInsensitive
error:&error];
NSTextCheckingResult* match = [regex firstMatchInString:stringToSearch options:0 range:NSMakeRange(0, [stringToSearch length])];
if(match.numberOfRanges == 2)
{
NSRange capture = [match rangeAtIndex:1];
NSString* URLString = [stringToSearch substringWithRange:capture];
NSLog(#"%#",URLString);
}

One Possible solution is by using NSScanner -
NSString *urlString = nil;
NSString *htmlString = #"Amazon <b>Kindle</b>: Welcome";
NSScanner *scanner = [NSScanner scannerWithString:htmlString];
[scanner scanUpToString:#"<a" intoString:nil];
if (![scanner isAtEnd]) {
[scanner scanUpToString:#"http" intoString:nil];
NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:#">"];
[scanner scanUpToCharactersFromSet:charset intoString:&urlString];
}
NSLog(#"%#", urlString);
In Logs -
https://kindle.amazon.com/&sa=U&ei=GdiWT5uCEI6BhQfihoTzDQ&ved=0CCUQFjAB&usg=AFQjCNEoRolsgoynLNS0H60VWz-9EaQdtw

Related

How can I replace strings between a pattern for an NSString?

Consider an NSString of the following pattern:
(foo('Class 0')bar('Class 1')baz('Class 2')
I just need to return foo, bar and baz. Any way I could at least replace 'Class 0' to some single character using regex?
I tried:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\(.*?\\)"
options:NSRegularExpressionCaseInsensitive
error:nil];
text = [regex stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, [text length]) withTemplate:#""];
If I understood your situation correctly, you needed to parse foo, bar, and baz out of the string above. The code below will do just that, and return foo, bar, and baz in an array.
As you will see in the code, we match on a word and an opening paren, and then trim the parens off programmatically. There may be a better regex that doesn't require the trimming, but I couldn't make that work with NSRegularExpression.
NSString *text = #"(foo('Class 0')bar('Class 1')baz('Class 2')";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[a-z]+[\(]"
options:NSRegularExpressionCaseInsensitive
error:nil];
NSMutableArray *output = [[NSMutableArray alloc] init];
[regex enumerateMatchesInString:text
options:0
range:NSMakeRange(0, [text length])
usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
NSString *rawMatch = [text substringWithRange:result.range];
NSString *trimmed = [rawMatch substringToIndex:(rawMatch.length - 1)];
[output addObject:trimmed];
}];
To get a string, like the one you mention in your comment above, just use
NSString *finalString = [output componentsJoinedByString:#" "];
I would just use:
NSString *string = #"foo('Class 0')bar('Class 1')baz('Class 2')";
NSString *output = [string stringByReplacingOccurrencesOfString:#"\\('[^')]*'\\)"
withString:#" "
options:NSRegularExpressionSearch
range:NSMakeRange(0, string.length)];
NSLog(#"%#", output); // foo bar baz
Replacing anything between (' and ') with a space. The pattern [^')] means that we don't want ) and 'letters to appear in between.

Trim an NSString Based Upon Number Of Character Occurrences

I'm trying to trim an NSString after I detect 3 new line instances. (\n). So, this is what I've tried:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\n" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [myString length])];
Now, number of matches will always exceed 3, and I want to stop the string right as it hits the third \n. Does any one know any good logic to do this?
If the 3 new line instances are always grouped together it's pretty easy:
NSString *testString = #"The quick brown fox jumps \n\n\n over the lazy dog. \n\n\n New Line.";
[[string componentsSeparatedByString:#"\n\n\n"] firstObject]
Otherwise you could use:
NSError *error;
NSString *pattern = #"(\\A|\\n\\s*\\n\\s*\\n)(.*?\\S[\\s\\S]*?\\S)(?=(\\Z|\\s*\\n\\s*\\n\\s*\\n))";
NSRegularExpression* regex = [[NSRegularExpression alloc] initWithPattern:pattern
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex enumerateMatchesInString:testString
options:0
range:NSMakeRange(0, [testString length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSString *match = [testString substringWithRange:[result rangeAtIndex:2]];
NSLog(#"match = '%#'", match);
}];
(Taken from this answer)
NSString* originalString = #"This\nis\na\ntest string";
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#".*\\n.*\\n.*\\n" options:0 error:nil];
NSRange range = [regex rangeOfFirstMatchInString:originalString options:0 range:(NSRange){0,originalString.length}];
NSString* trimmedString = [originalString substringFromIndex:range.length];
NSLog(#"Original: %#", originalString);
NSLog(#"Trimmed: %#", trimmedString);
Prints:
2015-02-05 21:39:41.491 TestProject[4258:1269568] Original: This
is
a
test string
2015-02-05 21:39:41.492 TestProject[4258:1269568] Trimmed: test string

how to use regular expressions NSRegularExpression for an NSMutableArray

I have the following code which works:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[a-cA-C2][m-oM-O][a-cA-C2]" options:0 error:NULL];
NSString *str = #"Ana";
NSTextCheckingResult *match1 = [regex firstMatchInString:str options:0 range:NSMakeRange(0, [str length])];
NSLog(#"check is exist: %#", [str substringWithRange:[match1 rangeAtIndex:0]]);
Here are my questions:
1.Is there a way I can change the NSString with an NSMutableArray and save the NSTextCheckingResult in a NSMutableArray called filterArray?
2.How to highlight the matching values when displaying then in a TextField?
If I correctly understand your question,
you want to use NSArray of strings, and receive NSArray of matching results for each string.
So, 1:
NSArray *arrayOfStrings = /* Your array */;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[a-cA-C2][m-oM-O][a-cA-C2]" options:0 error:NULL];
NSMutableArray *filterArray = [NSMutableArray array];
[arrayOfStrings enumerateObjectsUsingBlock:^(NSString * str, NSUInteger idx, BOOL * stop) {
NSTextCheckingResult *match = [regex firstMatchInString:str options:0 range:NSMakeRange(0, [str length])];
if (match) {
[filterArray addObject:match];
}
else {
[filterArray addObject:[NSNull null]];
}
NSLog(#"String #%i. check is exist: %#",idx, [str substringWithRange:[match rangeAtIndex:0]]);
}];
2: For highlighting ranges of the string you need to use NSAttributedString. Please, see this question for the answer how:) How do you use NSAttributedString?
After you formed attributed string, set it to textfield:
NSAttributedString * attributedString;
UITextField *textField;
[ttextField setAttributedText:attributedString];

how to fetch the string starts with &abc and ends with &

i like to know how to fetch the specific string which starts with &abc and ends with &. I tried with had prefix and sufix . but this is not new line ,
&xyz;123:183:184:142&
&abc;134:534:435:432&
&qwe;323:535:234:532&
my code :
NSMutableArray *substrings = [NSMutableArray new];
NSScanner *scanner = [NSScanner scannerWithString:s];
[scanner scanUpToString:#"&abc" intoString:nil]; //
NSString *substring = nil;
[scanner scanString:#"&abc" intoString:nil]; // Scan the # character
if([scanner scanUpToString:#"&" intoString:&substring]) {
// If the space immediately followed the &, this will be skipped
[substrings addObject:substring];
NSLog(#"substring is :%#",substring);
}
// do something with substrings
[substrings release];
how to make "scanner scanUpToString:#"&abc" and count ":"==3 till "#"???? can help me
NSArray *arr = [NSArray arrayWithObjects:#"&xyz;123:183:184:142&",
#"&abc;134:534:435:432&",
#"&qwe;323:535:234:532&",
#"& I am not in it",
#"&abc I am out &" ,nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self BEGINSWITH[cd] %# AND self ENDSWITH[cd] %#",#"&abc",#"&"];
NSLog(#"Sorted Array %#",[arr filteredArrayUsingPredicate:predicate]);
NSArray *sortedArray = [arr filteredArrayUsingPredicate:predicate];
NSMutableArray *finalResult = [NSMutableArray arrayWithCapacity:0];
for(NSString *string in sortedArray)
{
NSString *content = string;
NSRange range1 = [content rangeOfString:#"&abc"];
if(range1.length > 0)
content = [content stringByReplacingCharactersInRange:range1 withString:#""];
NSRange range2 = [content rangeOfString:#"&"];
if(range2.length > 0)
content = [content stringByReplacingCharactersInRange:range2 withString:#""];
[finalResult addObject:content];
}
NSLog(#"%#",finalResult);
Try using NSRegularExpression:
- (BOOL)isValidString:(NSString *)string
{
NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:#"^&abc.*&$" options:0 error:NULL];
NSTextCheckingResult *result = [regularExpression firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
return (result != nil);
}

Search tags in string

I have a string, and I want to search words (tags) that begin with "#" and end with "." or "," or " " I found this online, but is limited because:
- You can find a single word in the string (although there are more words)
- "RangeOfString" does not allow multiple choices
NSString *stringText = #"test #hello #world";
NSString *result = nil;
// Determine "#"
NSRange hashRange = [stringText rangeOfString:#"#" options:NSCaseInsensitiveSearch];
if (hashRange.location != NSNotFound)
{
// Determine " " location according to "#" location
NSRange endHashRange;
endHashRange.location = hashRange.length + hashRange.location;
endHashRange.length = [stringText length] - endHashRange.location;
endHashRange = [stringText rangeOfString:#" " options:NSCaseInsensitiveSearch range:endHashRange];
if (endHashRange.location != NSNotFound)
{
// Tags found: retrieve string between them
hashRange.location += hashRange.length;
hashRange.length = endHashRange.location - hashRange.location;
result = [stringText substringWithRange:hashRange];
}
}
you have idea how can I do?
Thank you!
You can use NSRegularExpression class, like this:
NSError *error = NULL;
NSRegularExpression *tags = [NSRegularExpression
regularExpressionWithPattern:#"[#]([^, .]+)([, .]|$)"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSArray *matches = [tags matchesInString:str options:0 range:NSMakeRange(0, str.length)];
for (NSTextCheckingResult *match in matches) {
NSLog(#"%#", [str substringWithRange:[match rangeAtIndex:1]]);
}
You may need to play with your regular expression to get it just right. The reference that I liked describes the grammar of the regex language supported by Apple's classes.
You should use NSRegularExpression, which will give you multiple matches.
The following is an untested example:
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\b(#\\S*[.,])\\b" options:NSRegularExpressionCaseInsensitive];
int numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, string.length)];
NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];
You will most likely want to use NSScanner.
NSString *stringText = #"test #hello #world";
NSString *result = nil;
NSCharacterSet *endingChars = [NSCharacterSet characterSetWithCharactersInString:#"., "];
NSScanner *scanner = [NSScanner scannerWithString:stringText];
scanner.charactersToBeSkipped = nil;
[scanner scanUpToString:#"#" intoString:NULL];
[scanner scanString:#"#" intoString:NULL];
[scanner scanUpToCharactersFromSet:endingChars intoString:&result];
[scanner scanCharactersFromSet:endingChars intoString:NULL];
STAssertEqualObjects(result, #"hello", nil);
At that point you just loop until [scanner isAtEnd];
NSString *stringText = #"test #hello #world";
NSString *match = nil;
NSMutableArray *results = [NSMutableArray arrayWithCapacity:2];
NSCharacterSet *endingChars = [NSCharacterSet characterSetWithCharactersInString:#"., "];
NSScanner *scanner = [NSScanner scannerWithString:stringText];
scanner.charactersToBeSkipped = nil;
while (![scanner isAtEnd]) {
[scanner scanUpToString:#"#" intoString:NULL];
[scanner scanString:#"#" intoString:NULL];
[scanner scanUpToCharactersFromSet:endingChars intoString:&match];
[scanner scanCharactersFromSet:endingChars intoString:NULL];
[results addObject:match];
}
STAssertEquals(results.count, 2, nil);
STAssertEqualObjects([results objectAtIndex:0], #"hello", nil);
STAssertEqualObjects([results objectAtIndex:1], #"world", nil);