Salesforce extract substring from string with regex - regex

I am developing an application in Salesforce with Apex and i need to extract a Substring from other string. This is the original String:
String str = 'Product: Multi Screen Encoder Version: 3.51.10 (008) Order Number: 0030000a9Ddy Part Number: 99-00228-X0-Y-WW02-NA01 Comment: some comments';
i Want to extract the value of Part Number so i am using the Matcher and Pattern classes:
Pattern p = Pattern.compile('Part Number: (.+)\\s');
Matcher pm = p.matcher(str);
if (pm.matches()) {
res = 'match = ' + pm.group(1);
System.debug(res);
} else {
System.debug('No match');
}
But i am getting No match.
How can i fix the regex to match correctly my String

You need to use find function instead of matches in the if condition.
Pattern p = Pattern.compile('Part Number: (\\S+)\\s');
Matcher pm = p.matcher(str);
if (pm.find()) {
res = 'match = ' + pm.group(1);
System.debug(res);
} else {
System.debug('No match');
}
\\S+ matches one or more non-space characters.
or
Pattern p = Pattern.compile('Part Number: (.+?)\\s');

Related

How do I use reaLline() to find matches in a file using regex and print them out to the console

I am trying to have the user input a class number and name to pull up a list of information on that class I have on a file. I have figured out how to match the information using .toRegex. I can't figure out how to use the users input to find the match they need and not all matching in the file. I am very new to Regnex.
val pattern = """\d+\s+([A-Z]+).\s+(\d+)\s.+\s+\w.+""".toRegex()
val fileName = "src/main/kotlin/Enrollment.txt"
var lines = File(fileName).readLines()// reads every line on the file
do{
print("please enter class name")
var className = readLine()!!
print("please enter class number ")
var classNum = readLine()!!
for(i in 0..(lines.size-1) ){
var matchResult = pattern.find(lines[i])
if(matchResult != null) {
var (className,classNum) = matchResult.groupValues
println("className: $className, class number: $classNum ")
}
}
}while (readLine()!! != "EXIT") ```
example line from file
Name Num
0669 HELP 134 AN CV THING ETC 4.0 4.0 Smith P 001 0173 MTWTh 9:30A 10:30A 23 15 8 4.0
See MatchResult#groupValues reference:
This list has size of groupCount + 1 where groupCount is the count
of groups in the regular expression. Groups are indexed from 1 to
groupCount and group with the index 0 corresponds to the entire
match.
If the group in the regular expression is optional and there were no
match captured by that group, corresponding item in groupValues
is an empty string.
You need
var (_, className,classNum) = matchResult.groupValues
See Kotlin demo:
val lines = "0669 HELP 134 AN CV THING ETC 4.0 4.0 Smith P 001 0173 MTWTh 9:30A 10:30A 23 15 8 4.0 "
val pattern = """^\d+\s+([A-Z]+)\s+(\d+)""".toRegex()
var matchResult = pattern.find(lines)
if(matchResult != null) {
var (_, className,classNum) = matchResult.groupValues
println("className: $className, class number: $classNum ")
}
// => className: HELP, class number: 134
I simplified the regex a bit since find() does not require a full string match to
^\d+\s+([A-Z]+)\s+(\d+)
See the regex demo. Details:
^ - start of string
\d+ - one or more digits
\s+ - one or more whitespaces
([A-Z]+) - Group 1: one or more uppercase ASCII letters
\s+ - one or more whitespaces
(\d+) - Group 2: one or more digits
You need to use a variable in the pattern that you get from the user .readLine()
Use a loop to check each line with another loop checking if the patter is in that line. pattern.containMatchIn()
val className = readLine()!!.toUpperCase()
print("please enter class number ")
val classNum = readLine()!!
val pattern = """\s+\d+\s+$className.\s+$classNum""".toRegex()
for(i in 0..(lines.size-1) ) {
var matchResult = pattern.find(lines[i])
if(matchResult != null ){
if (pattern.containsMatchIn(lines[i])) {
println(lines[i])
}
}
}```

How to extract a substring from string using regex

code
I want regex for this format and filter out 123456 if match the current format
PO # 123456
PO# 123456
PO #123456
P.O. # 123456
P.O.# 123456
P.O. #123456
We have to filter substring from string notes__c field. my regex is only working for PO #123456 and P.O. #123456
Matcher rm = r.matcher(oOrder.Notes__c);
Pattern r = Pattern.compile('PO #(\\S+)\\s');
if(rm.find()) {
string res2 = rm.group(1);
oOrder.test__c = res2;
}
Try this:
.?(\d+)$
For the example you posted it works.
https://regex101.com/r/eTjbMo/1/
The key thing to note here are the optional whitespace. Whitespace can appear before and/or after the #. Whenever you see a pattern like this, you usually need \s* (if you allow multiple whitespace) or \s? (if you only allow one or more whitespace).
The first part can either be PO or P.O.. We can write these two alternatives with the | token. Remember to escape the .s.
The whole regex looks like this:
(?:PO|P\.O\.)\s*#\s*(\d+)
Here, I assumed the thing you want to capture matches \d+. If that part can contain letters, change the capture group accordingly.
Demo
To write the regex as a string literal, you need to escape the backslashes:
(?:PO|P\\.O\\.)\\s*#\\s*(\\d+)
Above codes are not working friends
i HAVE MODIFIED MY CODE TO
if(oOrder.Notes__c != null) {
Pattern p = Pattern.compile('PO # (\\S+)\\s');
Pattern q = Pattern.compile('PO# (\\S+)\\s');
Pattern r = Pattern.compile('PO #(\\S+)\\s');
Pattern s = Pattern.compile('P.O. # (\\S+)\\s');
Pattern t = Pattern.compile('P.O.# (\\S+)\\s');
Pattern u = Pattern.compile('P.O. #(\\S+)\\s');
Matcher pm = p.matcher(oOrder.Notes__c);
Matcher qm = q.matcher(oOrder.Notes__c);
Matcher rm = r.matcher(oOrder.Notes__c);
Matcher sm = s.matcher(oOrder.Notes__c);
Matcher tm = t.matcher(oOrder.Notes__c);
Matcher um = u.matcher(oOrder.Notes__c);
system.debug('find = ' +pm.find());
if (pm.find()){
string res = pm.group(1);
oOrder.test__c = res;
}
if(qm.find()){
string res1 = qm.group(1);
oOrder.test__c = res1;
}
if(rm.find()){
string res2 = rm.group(1);
oOrder.test__c = res2;
}
if(sm.find()){
string res3 = sm.group(1);
oOrder.test__c = res3;
}
if(tm.find()){
string res4 = tm.group(1);
oOrder.test__c = res4;
}
if(um.find()){
string res5 = um.group(1);
oOrder.test__c = res5;
}
}
it is covering everything except First one
PO # 123456

Regular expression to limit number of digits

I am trying to write a regular expression that will only match with qtr1, qtr2, qtr3, qtr4 with help of following regex [q|qtr|qtrs|quarter]+[1-4] but the problem is if i ask something like this "Ficoscore for Q21 2005" a space is added between Q and 21 ie "Ficoscore for Q 21 2005" this not valid.
String regEx = "([q|qtr|qtrs|quarter]+[1-4])";
Pattern pattern = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(userQuerySentence);
System.out.println(matcher.matches());
while (matcher.find()) {
String quarterString = matcher.group();
userQuerySentence = userQuerySentence.replaceAll(quarterString,
(quarterString.substring(0, quarterString.length() - 1) + " " + quarterString.substring(quarterString
.length() - 1)));
}
[q|qtr|qtrs|quarter] is a character class, I guess you want (q|qtr|qtrs|quarter):
String regEx = "(?i)\\b((?:q(?:trs?|uarter)?)[1-4])\\b";

Java Matcher Error

My string:
null[00:14.04]I've /n[00:14.11]got /n[00:14.18]a /n[00:14.25]fee- /n[00:15.02]ling /n
I am trying to obtain every data between [<--->] brackets. Here's my code.
String find = "[(.*?)\\\\]";
Pattern patern = Pattern.compile(find);
Matcher matcher = patern.matcher(intake);
while(matcher.find()){
i++;
matcher.find(i);
int start = matcher.start();
int end = matcher.end();
String group = matcher.group();
}
The first results are:
start = 10
end = 11
group = "."
What I wanted was (Counting on my head)
start = 4
end = 14
group = [00:14.04]
Next is
start = 22
end = 32
group = [00:14.11]
and so on
What is the correct pattern?
You're using wrong escaping. Use this regex:
String find = "\\[(.*?)\\]";
EDIT: Based on your comment:
If you want to capture all items inside square brackets just run your while loop like this:
while(matcher.find()) {
String matched = matcher.group(1);
System.out.printf("Matched Group: [%s]%n", matched);
}

Regular expression that matches string equals to one in a group

E.g. I want to match string with the same word at the end as at the begin, so that following strings match:
aaa dsfj gjroo gnfsdj riier aaa
sdf foiqjf skdfjqei adf sdf sdjfei sdf
rew123 jefqeoi03945 jq984rjfa;p94 ajefoj384 rew123
This one could do te job:
/^(\w+\b).*\b\1$/
explanation:
/ : regex delimiter
^ : start of string
( : start capture group 1
\w+ : one or more word character
\b : word boundary
) : end of group 1
.* : any number of any char
\b : word boundary
\1 : group 1
$ : end of string
/ : regex delimiter
M42's answer is ok except degenerate cases -- it will not match string with only one word. In order to accept those within one regexp use:
/^(?:(\w+\b).*\b\1|\w+)$/
Also matching only necessary part may be significantly faster on very large strings. Here're my solutions on javascript:
RegExp:
function areEdgeWordsTheSame(str) {
var m = str.match(/^(\w+)\b/);
return (new RegExp(m[1]+'$')).test(str);
}
String:
function areEdgeWordsTheSame(str) {
var idx = str.indexOf(' ');
if (idx < 0) return true;
return str.substr(0, idx) == str.substr(-idx);
}
I don't think a regular expression is the right choice here. Why not split the the lines into an array and compare the first and the last item:
In c#:
string[] words = line.Split(' ');
return words.Length >= 2 && words[0] == words[words.Length - 1];