I need a regex to find string literals in iOS source code.
I want to collect them and then use in other place.
I need the regex to be able to parse next cases. Comments will be stripped beforehand:
char c = '"'; /* Not a string*/ NSString * *str1 = #"string"; // Here's a string
NSString *str2 = #"\"A\" class";
NSString *str3 = #"Long long"
#"long long string";
NSString *str4 = #"Another Long long"
"long long string";
NSString *str5 = #"Long untrimmed \
string";
I'm not very good with regex. I've tried this one:
#"(?<!')\"((\\\\\")*[^\"\\r\\n]*(\\\\\")*)*\"'{0}"
Unfortunately it hangs on such strings.
Hello here is your solution "(\\.|[^"])*\" use this regex to parse string literals in any text. you can check this regex on sample text on http://regexpal.com/
hope is helps !
#(\".*\";|\".*\n.*\";|\".*\")
Check http://rubular.com/r/6dxtBzTE7P . I could not do 3rd one fully correct.
I end up with following regex (^|[^'])(#?\"([^\"\\\\]|(\\\\.)|(\\\\\n)|(\"\\s*#?\"))*\"), example:
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:#"(^|[^'])(#?\"([^\"\\\\]|(\\\\.)|(\\\\\n)|(\"\\s*#?\"))*\")" options:NSRegularExpressionAnchorsMatchLines error:&error];
[regex enumerateMatchesInString:source options:0 range:NSMakeRange(0, [source length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSLog(#"%#\n\n", [source substringWithRange:[result rangeAtIndex:2]]);
}];
It works fine for any cases that I have in my mind plus it also works for c-string.
How it works:
(^|[^']) Any character except ' (because '"') or beginning of line
#?\"([^\"\\\\]|(\\\\.)|(\\\\\n)|(\"(\\s*\\n*\\s*)*#?\"))*\" starts with #" or " and ends with ".
Between can be any sequence of character except " or \ ([^\"\\\\])
it can be \ char then skip next element too, it escaped anyway (\\\\.)
it can be escaped next line symbol (\\\\\n)
it can be multiline string, so we skip all whitespaces and new line symbols. Next line in string can be both from " and #" (#?\"\\s*#?\")
Check online editor: http://regex101.com/r/gG0sF2
Related
Stuck on below.
I am going to replace "" (Double quotes) from textfield text and send that text in json request parameter but below code is not working
NSString * mString = textfield.text; // Input through ipad/iphone/simulator keypad.
[mString replaceOccurrencesOfString:#"\"" withString:#"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mString length])];.
But if i hardcode NSString * mString = #"\"test"; // Input through xcode
replaceOccurrencesOfString: is working.
Is the issue with Double quote Input encoding.?
Why does the Double quote from ipad/iphone/simulator keypad not working same as xcode Double quote.
Thanks.
By default, the iOS keyboard uses "smart" quotes... it uses left double quotation mark when you open a quoted string portion, and right double quotation mark when you close the quoted portion.
So to strip those, you'll need to replace double-quote AND left-double-quote AND right-double-quote.
Here's a quick example:
NSString *origString = _myTextField.text;
NSString *strippedString = [origString copy];
NSArray *replaceChars = #[#"”", #"“", #"\""];
for (NSString *c in replaceChars) {
strippedString = [strippedString
stringByReplacingOccurrencesOfString:c
withString:#""];
}
NSLog(#"Orig: [%#] / Stripped: [%#]", origString, strippedString);
Example output:
Orig: [“test”] / Stripped: [test]
You have to look close, but you'll see the left- and right-double-quote-marks.
Edit
A much more concise way:
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:#"”“\""];
NSString *strippedString = [origString stringByTrimmingCharactersInSet:set];
NSLog(#"Orig: [%#] / Stripped: [%#]", origString, strippedString);
But, as noted by Sulthan, you may need to consider other languages' punctuation.
I am trying to parse a string in Objective-C to delete an exact match of a specific #tagged word. I can create a regular expression and delete a specific word without issue, but when I try to remove a string with a leading "#" it's not working.
Here's my code:
NSString *originalString = #"This is just a #test that isn't working";
NSString *hashTag = #"#test";
NSString *placeholder = #"\\b%#\\b";
NSString *pattern = [NSString stringWithFormat:placeholder, hashTag];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
NSString *modifiedString = [regex stringByReplacingMatchesInString:originalString
options:0
range:NSMakeRange(0, [originalString length])
withTemplate:#""];
The issue is that even if the original string includes the string #test, it's not removed. If I swap "#test" with "test", everything works fine, but that's not what I'm trying to do. What am I missing?
Because there isn't a word character exists between a space and #. Both are non-word characters. So i suggest you to remove the starting \\b
NSString *placeholder = #"%#\\b";
OR
Use a negative lookbehind.
NSString *placeholder = #"(?<!\\S)%#\\b";
(?<!\\S) Negative lookbehind which asserts that there isn't a non-space character exists before the match.
To do an exact string match, i suggest you to use this #"(?<!\\S)%#(?!\\S)" regex. (?!\\S) Negative lookahead which asserts that the match won't be followed by a non-space character.
DEMO
is it even necessary to use a regex, would this function not suffice?
[yourstring stringByReplacingOccurrencesOfString:#"#test" withString:#""];
My app puts a space after the ":" in case the user forgets to. Like so:
input = [input stringByReplacingOccurrencesOfString:#":" withString:#": "];
This works well if they type in English. It will make "My friends are:James.." into "My friends are: James..." and this is fine.
BUT the problem I'm having is it also ads a space within a time. It will make "12:30" into "12: 30". I could make a bunch of these codes with all the number possibilities to fix, which is too much.
input = [input stringByReplacingOccurrencesOfString:#": 0" withString:#":0"];
What is the easier way to do this? I've tried:
input = [input stringByReplacingOccurrencesOfString:#"\\b\\d\\d?:\\s\\d\\d\\b" withString:#"\\b\\d\\d?:\\d\\d\\b" options: NSRegularExpressionSearch range:NSMakeRange(0, [input length])];
But all that does is change ALL times from "hh: mm" to "bdd?:ddb" and that's it. how do I make an NSString replacement retain it's previous characters? Like how can I make it still keep the same numbers that were previously put? All I want to change is the ": " to be ":" in a time.
I've tried "if" statements with NSNotFound but it wasn't working. I wanted it that if it found a "hh:mm" format, to NOT add a space, but if it didn't, to add a space but that didn't work.
You were on the right lines with the last version, but you need to use NSRegularExpression. The following should do the whole thing for you (adding spaces after colons, but not when sandwiched between double digits or already followed by a space):
NSString *input = #"My friends are:James, John. It's 10:30 right now.";
NSMutableString *workingString = [input mutableCopy];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(((?<!(\\b\\d\\d)):)|(:(?!(\\d\\d\\b))))(?!\\s)" options:0 error:nil];
[regex replaceMatchesInString:workingString options:0 range:NSMakeRange(0, [workingString length]) withTemplate:#": "];
input = [workingString copy];
NSLog(#"%#", input); // Prints "My friends are: James, John. It's 10:30 right now."
You can do it in this way..If you have either time in string or only sentence with no numbers...
NSCharacterSet *s = [NSCharacterSet characterSetWithCharactersInString:#"1234567890"];
NSRange r = [input rangeOfCharacterFromSet:s];
if (r.location != NSNotFound)
{
input = [input stringByReplacingOccurrencesOfString:#":" withString:#": "];
}
Hope it helps you..
I have tried (searching for) various possible solutions here on SO, in vain. Most of them simply replace all occurrences of backslashes, and don't respect backslashes that should otherwise be untouched.
For instance, if I have a Hi, it\'s me. How\'re you doing?, it should be Hi, it's me. How're you doing?. However, if someone tries to get creative with ASCII art, like
\\// \\// \\//
//\\ //\\ //\\
(WOW even SO won't let me add text as is, the above text needed extra backslashes to be displayed correctly.)
I cannot use [myString stringByReplacingOccurrencesOfString:#"\\" withString:#""]; since it will replace ALL backslashes. I do not want that.
I would like the string to be displayed as is.
NOTE: The strings in question here are values in NSDictionarys received as JSON from a web service. The use is in a service like a chat client, so it is important that text is handled correctly.
ULTRA IMPORTANT NOTE: I'm open to all ideas like library functions, regular expressions, human sacrifices, as long it gets the job done.
try this ...i cannot understand your question but it may help full for you,i think so
- (void)remove:(NSString*)str
{
NSString* const pattern = #"(\"[^\"]*\"|[^, ]+)";
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern
options:0
error:nil];
NSRange searchRange = NSMakeRange(0, [str length]);
NSArray *matches = [regex matchesInString:str
options:0
range:searchRange];
for (NSTextCheckingResult *match in matches) {
NSRange matchRange = [match range];
NSLog(#"%#", [str substringWithRange:matchRange]);
}
NSLog(#"%#",str);
}
call this method..
NSString* str = #"Hi, it\'s me. How\'re you doing?";
[self remove:str];
then the output is
Hi, it's me. How're you doing?
I need to turn something like this
NSString *stringWithParentheses = #"This string uses (something special)";
Into this, programmatically.
NSString *normalString = #"This string uses";
The issue is I don't want to use all these weird libraries, regex, etc.
If you change your mind about the regex, here's a short, clean solution:
NSString *foo = #"First part (remove) (me (and ((me)))))) (and me) too))";
NSRegularExpression *expr = [NSRegularExpression regularExpressionWithPattern:#"\\(.*\\)" options:0 error:NULL];
NSString *bar = [expr stringByReplacingMatchesInString:foo options:0 range:NSMakeRange(0, foo.length) withTemplate:#""];
Everything between ( and ) gets removed, including any nested parentheses and unmatched parentheses within parentheses.
Just find the first open parentheses, note its index, find the closing one, note its index, and remove the characters between the indexes (including the indexes themselves).
To find the character use:
[string rangeOfString:#"("];
To remove a range:
[string stringByReplacingCharactersInRange:... withString:#""];
Here is a solution:
NSString* str = #"This string uses (something special)";
NSRange rgMin = [str rangeOfString:#"("];
NSRange rgMax = [str rangeOfString:#")"];
NSRange replaceRange = NSMakeRange(rgMin.location, rgMax.location-rgMin.location+1);
NSString* newString = str;
if (rgMin.location < rgMax.location)
{
newString = [str stringByReplacingCharactersInRange:replaceRange withString:#""];
}
It won't work on nested parentheses. Or multiple parentheses. But it works on your example. This is to be refined to your exact situation.
A way would be to find the position of the first occurrence of the '(' character and the last occurrence of the ')' character, and to build a substring by eliminating all the characters between these ranges. I've made an example:
NSString* str= #"This string uses (something special)";
NSRange r1=[str rangeOfString: #"("];
NSRange r2= [str rangeOfString: #")" options: NSBackwardsSearch];
NSLog(#"%#",[str stringByReplacingCharactersInRange: NSMakeRange(r1.location, r2.location+r2.length-r1.location) withString: #""]);