Provisioning code regular expression - c

I'm trying to develop a C code that checks the validity of "Provisioning code" string using regular expressions.
A "provisioning code" format should respect the following law:
If not an empty string, this argument SHOULD be in the form of a hierarchical descriptor with one or more nodes specified. Each node in the hierarchy is represented as a 4-character sub-string, containing only numerals or upper-case letters. If there is more than one node indicated, each node is separated by a "." (dot). Examples: "TLCO" or "TLCO.GRP2".
I started development using the code in this link http://web.archive.org/web/20160308115653/http://peope.net/old/regex.html
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
int main(int argc, char *argv[]){
regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(&regex, "^a[[:alnum:]]", 0);
if( reti ){ fprintf(stderr, "Could not compile regex\n"); exit(1); }
/* Execute regular expression */
reti = regexec(&regex, "abc", 0, NULL, 0);
if( !reti ){
puts("Match");
}
else if( reti == REG_NOMATCH ){
puts("No match");
}
else{
regerror(reti, &regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free compiled regular expression if you want to use the regex_t again */
regfree(&regex);
return 0;
}
this code works fine but my problem is what's the best regular expression that should be input of the function regcomp.
I started to try with a regular expression that matches with string that contains exactly 4 characters uppercases or numerals that means example like TLCO or TLC2 trying with the regular expression "[A-Z0-9]{4}" but I get "No match" as output with matches examples like TLC2.
Is there a suggestion about the right regular expression that should be input of regcomp and matches with "provisioning code"?

You may use the following regex that will work alright if you also pass REG_EXTENDED flag to the regcomp method (for the $ and {m,n} modifier to work correctly):
^[A-Z0-9]{4}([.][A-Z0-9]{4})*$
C code:
reti = regcomp(&regex, "^[A-Z0-9]{4}([.][A-Z0-9]{4})*$", REG_EXTENDED);
Details
^ - start of string
[A-Z0-9]{4} - 4 uppercase ASCII letters or digits
([.][A-Z0-9]{4})* - zero or more sequences of:
[.] - a literal . char
[A-Z0-9]{4} - 4 uppercase ASCII letters or digits
$ - end of string.

Related

Issues with regular expression rejecting string

regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression, if two vowels it should be ok */
reti = regcomp(&regex, "[aoueiy].{2}", 0);
if (reti){
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(&regex, "ao", 0, NULL, 0);
if (!reti) {
puts("Match");
}
else if (reti == REG_NOMATCH) {
puts("No match");
}
I am trying to write an expression that is supposed to accept an string that contains at least two vowels. Here is my code so far, the string ao gives me "No match". I am new to regex and I find the manual hard to use. Very thankful for any help or tips.
Your regular expression matches a vowel followed by 2 other characters. [aoueiy] matches a vowel, . matches any characters, and adding {2} after it makes it match two characters. ao only has 1 character after the vowel, so it doesn't match.
The correct regexp is [aoueiy].*[aoueiy]. This matches two vowels with any number of characters (including 0) between them.

Start (^) and end ($) anchors not working

Basically I'm using following pattern in my C program (See Regular expression matching an infinite pattern):
^[0-9]( [0-9])*$
with following code:
char *pattern = "^[0-9]( [0-9])*$";
regex_t regexCompiled;
int rc = regcomp(&regexCompiled, pattern, REG_EXTENDED);
if (rc != 0) {
char msgbuf[100];
regerror(rc, &regexCompiled, msgbuf, sizeof (msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(EXIT_FAILURE);
}
if (regexec(&regexCompiled, "0 1", 0, NULL, REG_EXTENDED) == 0) {
printf("Valid\n");
} else {
printf("Invalid\n");
}
Where I exec against the string "0 1", which is valid for the pattern and it's not working. The '^' and '$' are not functioning. Why is that? and how can I make it work?
You are passing REG_EXTENDED to regexec(), that's not a valid flag for that call.
The manual page says:
eflags may be the bitwise-or of one or both of REG_NOTBOL and REG_NOTEOL which cause changes in matching behavior described below.
Probably the actual value of REG_EXTENDED matches one of those.
Changing the code to pass 0 as the final argument to regexec() makes it match.

Unable to match regex in C

I have a problem with following regex:
prefix:\w+,\w+,\s*-?[0-9]{1,4}\s*,\s*-?[0-9]{1,4}\s*,\s*-?[0-9]{1,4}\s*,(?:\w+)
The match string is the following:
prefix:string,string,-100,100,0,string
I cannot match this string in my C code. At least I get a successful match on some online tool where I generated this regex. Also there were compilation warnings about "\" characters in regex so I replaced it as explained in c-compiler-warning-unknown-escape-sequence-using-regex-for-c-program. Regex after compilation warning fixes:
prefix:\\w+,\\w+,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,(?:\\w+)
Here's the testing code:
#include <stdio.h>
#include <regex.h>
#include <stdlib.h>
#define REGEX "prefix:\\w+,\\w+,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,(?:\\w+)"
const char *input = "prefix:string,string,-100,100,0,string";
int main(){
int rc;
regex_t regex;
rc = regcomp(&regex, REGEX, 0);
if (rc != 0) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
rc = regexec(&regex, input, 0, NULL, 0);
if (rc == 0) {
printf("Match!\n");
return 0;
}
else if (rc == REG_NOMATCH) {
printf("No match\n");
return -1;
}
else {
perror("Error\n");
exit(1);
}
return 0;
}
I use gcc version 6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12)
You need to do two things:
Use REG_EXTENDED flag to compile the regex (so that extended regular expression flavor (ERE) is enabled), else the limiting quantifier will need escaping, and there may be other potential issues
Remove the non-capturing group (?:...) as POSIX does not support this construct.
To make \w+ optional, just replace (?:\w+) with \w*.
Use
#define REGEX "prefix:\\w+,\\w+,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\w*"
^^^
and then
rc = regcomp(&regex, REGEX, REG_EXTENDED);
^^^^^^^^^^^^
See the C demo.
Also, see more about the Extended Regular Expressions that are enabled by REG_EXTENDED, and POSIX Bracket Expressions is also a good resource to learn differences between BRE (Basic Regular Expressions) and ERE flavors.

Posix regular expression not working in C

This is my first time working with regex in C and I am having some trouble. I am trying to replicate a syntax that is used in sed, namely the s/findthisstring/replacewiththis/g where findthisstring has to be present and replacewiththis does not.
The regex I came up with is ^s/(.*)/(.*)/g$
Here it is in my code
int verifyPattern(char *pattern) {
regex_t regex;
int reti = regcomp(&regex, "^s/(.*)/(.*)/g$", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
reti = regexec(&regex, pattern, 0, NULL, 0);
if (!reti) {
puts("Match");
} else if (reti == REG_NOMATCH) {
puts("No match");
} else {
puts("Regex error");
}
return 1;
}
I believe the part that is messing up is the .+. If I replace it with .* everything is fine. Anyone know a work around for this??
Thanks!
You forgot to pass the REG_EXTENDED flag to allow $ in the pattern. Also, your regex would allow too many /.../ sections. What you need is to match either an escape sequence or a char other than / and \:
int reti = regcomp(&regex, "^s/(\\\\.|[^\\\\/]+)+/(\\\\.|[^\\\\/]+)*/g$", REG_EXTENDED);
See the C demo
Basically, I replaced . with (\\.|[^\\/]+) pattern matching either an escape sequence (\\.) or (|) one or more characters other than \ and /.
Here is a list of tests:
verifyPattern("s/s/s/g");//Match
verifyPattern("s/s//g");//Match
verifyPattern("s//s/g");//No Match
verifyPattern("s/s\\/s/g");//No match
verifyPattern("s/s\\/s/text/text/text/g"); // No match

Regular Expression in C

I'm trying to match a string "123,1234" using regex.h. Following pattern does the job:
"^[0-9]\{1,\},[0-9]\{1,\}$"
If I'm giving it as a commandline argument it works fine. But when I use it inside C code it does not work. Probably because identifying backward slashes as escape characters.
Sample Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
int main (int argc, char * argv[]){
regex_t regex;
int reti;
char msgbuf[100];
char * string, * pattern;
string = "123,1234";
pattern = "^[0-9]\{1,\},[0-9]\{1,\}$";
if(regcomp(&regex, pattern, 0))
{
fprintf(stderr, "Could not compile regex\n");
exit(107);
}
if(!(reti = regexec(&regex, string, 0, NULL, 0)))
{
printf("MATCH\n");
}
else if(reti == REG_NOMATCH)
{
printf("NO MATCH\n");
}
else
{
regerror(reti, &regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(107);
}
regfree(&regex);
return 0;
}
How can I solve this?
Your regular expression is an ERE not a BRE, so you need to pass the REG_EXTENDED flag to regcomp. Then, as others have said, remove the backslashes too.
^[0-9]{1,},[0-9]{1,}$
Take out the \ backslashes. They escape the character immediately following.
To override the slash as an escape sequence, in C one uses a slash to escape a slash, so \ becomes \\.
However, since you are not passing the string to the command line, the curly braces { and } are not going to be caught by the shell's parser, so you could just try it without all of the slashes.
"^[0-9]{1,},[0-9]{1,}$"
If the slashes are being treated as escape characters, have you tried doubling up the slashes so that they are treated as escaped slashes?
ie
"^[0-9]\\{1,\\},[0-9]\\{1,\\}$"

Resources