I have string in format:
172.60.136.145,172.60.136.146,172.60.136.147,........
and I need help in validating the IpAddresses in the string using Regex
For specific such as above
172\.60\.136\.[0-9]{1-3}
which nails it specifically to the range of 172.60.136.0 through 999
of course that doesnt cover valid only IPs, that would allow 172.60.136.0 or 172.60.136.999
(0?0?[1-9]|0?[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])(\\.(0?0?[0-9]|0?[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])){2}(\\.(0?0?[1-9]|0?[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))
Does test that the IP is valid, it allows 1.0.0.1, through 254.254.254.254, wont allow anything ending in .0 etc.
In PHP:
$tmp = explode(',', $ips);
$tmp = array_map('ip2long', $tmp);
if (array_search(false, $tmp, true) !== false) {
// at least one ip is invalid
}
I'm not sure regex is your best option here as ip addresses are only valid if the numbers are 254 or less
I would split the string at the commas and then split each one of those by a period. I would check that there are 4 sections and that each section can be converted to a number which is 254 or less.
something like this untested pseudo code
string[] addresses = myString.Split(",");
foreach(string address in addresses)
{
string[] numbers = address.Split(".");
if (numbers.Length==4)
{
Foreach(string number in numbers)
{
// need to check that the last number is not a zero as well - not shown here
int value = Convert.ToInt32(number);
if (value<0 && value>254)
{
//invalid
}
}
}
else
{
//invalid
}
}
there are probably classes you could use in your language to help with this but you don't say what language it is. You could do this in c#:
string[] addresses = myString.Split(",");
foreach(string address in addresses)
{
IpAddress ipAddress;
if (!IpAddress.TryParse(address, out ipAddress))
{
//invalid
}
}
if you just wanted to invalid ones you could do:
IPAddress ipAddress;
string[] addresses = myString.Split (",");
foreach (string address in addresses.Where (address => !IPAddress.TryParse (address, out ipAddress)))
{
//all elements in this loop will be invalid entries
// remove the '!' to get only the valid ones
}
Try with:
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
Related
I'm trying to evaluate a string against a set list of parameters with RegExp in Flutter. For example, the string must contain at least:
One capital letter
One lowercase letter
One number from 0-9
One special character, such as $ or !
This is basically for a password entry field of an application. I have set things up, firstly using validateStructure as follows:
abstract class PasswordValidator {
bool validateStructure(String value);
}
Then, I have used the RegExp function as follows:
class PasswordValidatorSpecial implements PasswordValidator {
bool validateStructure(String value) {
String pattern =
r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!##\$&*~£]).{8,}$';
RegExp regEx = new RegExp(pattern);
return regEx.hasMatch(value);
}
}
This does work well, in a sense that when I pass a string/password through it, it does tell me if at least one of the criteria is not met. However, what I would like to do is for the output to be more specific, telling me which of those criteria isn't met.
For example, if the password were to have everything but a number (from 0-9) I would want to be able to get the output to specifically say that a number is missing, but everything else is present.
How would I adapt my code to be able to do that? I thought perhaps by using conditional 'if' statement, although I don't know how that would work. Thanks!
That's right, you can use RegExr to check your RegExp, separate each part and use them separately to have a custom error. Also instead of return a bool value, you can return a String value, such as the following function:
String validateStructure(String value) {
String patternUpperCaseCharacters = r'^(?=.*?[A-Z])';
String patternLowerCaseCharacters = r'^(?=.*?[a-z])';
String patternNumbers = r'^(?=.*?[0-9])';
String patternSpecialCharacters = r'^(?=.*?[!##\$&*~£])';
RegExp regEx = new RegExp(patternUpperCaseCharacters);
if (regEx.hasMatch(value)) {
regEx = new RegExp(patternLowerCaseCharacters);
if (regEx.hasMatch(value)) {
return "More errors";
} else {
return "You need at least one lowercase letter";
}
} else {
return "You need at least one capital letter";
}
}
I'm trying to modify a regex so it will allow an empty value or alphanumeric only.
I currently have this, but it only validates the alphanumeric
if (ruletype eq "alphanumeric") {
bMatch = true;
variables.fieldName = listGetAt(arguments.rules[nRow],2,",");
if (structKeyExists(arguments.form, "#variables.fieldName#")){
if (NOT RefindNoCase("[[:alnum:]]",arguments.form[variables.fieldName])) {
lstError = listAppend(lstError,nRow,",");
}
} else {
lstError = listAppend(lstError,nRow,",");
}
}
I tried converting to rematch to find the empty value, but that also accepts the value 1234^%^&& which contains special characters. I'm not sure how to fix that.
Do I understand correctly, from the value you mention, that arguments.form[variables.fieldName] is a comma-delimited list? If so, then what is to be matched is each list-item.(Incidentally, the # in sdkfk364563!##$% has to be delimited).
A possible answer is then:
if (structKeyExists(arguments.form, variables.fieldName)){
// Assuming arguments.form[variables.fieldName] is a comma-delimited list
fieldNameArray=listToArray(arguments.form[variables.fieldName], ',', true);
for (fieldValue in fieldNameArray) {
fieldValue=trim(fieldValue);
if (fieldValue eq "" or REfindNoCase("^[a-zA-Z0-9]*$",fieldValue) eq 0) {
lstError = listAppend(lstError,nRow);
}
}
}
[[:alnum:]] is POSIX syntax, which may not be supported. Use the universal ASCII syntax, [a-zA-Z0-9]. Also modify your code to account for the presence of an integer and to rule out any possible space character.
if (structKeyExists(arguments.form, variables.fieldName)){
if (REfindNoCase("^[a-zA-Z0-9]*$",trim(arguments.form[variables.fieldName])) eq 0) {
lstError = listAppend(lstError,nRow);
}
}
Below is the regex which validates my passwords:
(((?=.*\\d{2,20})(?=.*[a-z]{2,20})(?=.*[A-Z]{3,20})(?=.*[##$%!##%&*?_~,-]{2,20})).{9,20}[^<>'\"])
Basically what I want is that it contains all above given characters in password. But it needs those characters in sequence e.g
it validates 23aaAAA#!, but it does not validatea2#!AAAa.
Simply add nested capturing groups to keep the chars validation not strictly as a sequence. The regex can be also simplified as follow (without extra groups):
(?=(?:.*[0-9]){2,20})
(?=(?:.*[a-z]){2,20})
(?=(?:.*[A-Z]){3,20})
(?=(?:.*[##$%!&*?_~,-]){2,20})
.{9,20}
[^<>'\"] # This matches also the newline char, i don't think you really want this...
In java use it as follows to match the :
String regex = "(?=(?:.*[0-9]){2,20})(?=(?:.*[a-z]){2,20})(?=(?:.*[A-Z]){3,20})(?=(?:.*[##$%!&*?_~,-]){2,20}).{9,20}[^<>'\"]";
String password = "23aaA#AA!#X"; // This have to be 10 chars long at least, no newline
if (password.matches(regex))
System.out.println("Success");
else
System.out.println("Failure");
The regex requires a password with (all not strictly in sequence):
(?=(?:.*[0-9]){2,20}): 2 numbers
(?=(?:.*[a-z]){2,20}): 3 lowercase lettes
(?=(?:.*[A-Z]){3,20}): 3 uppercase letters
(?=(?:.*[##$%!&*?_~,-]){2,20}): 2 of the symbols in the chars group
.{9,20}: Min length of 9 and max of 20
[^<>'\"]: One char that is not in (<,>,',") (NOTE: this matches also the newline)
So the min/max is actually 10/21 but the last statemente matches also the newline, so in the online regex demo, the visible chars will be between 9 and 20.
Regex online demo here
I would not try to build a single regexp, because nobody will ever be able to read nor change this expression ever again. It's to hard to understand.
"a2#!AAAa" will never validate because it needs 2 digits.
If you want a password, that contains a minmuum and maximum number of chars from a group. simply count them.
public class Constraint {
private Pattern pattern;
public String regexp = "";
public int mincount=2;
public int maxcount=6;
public Constraint(String regexp, int mincount, int maxcount) {
this.mincount=mincount;
this.maxcount=maxcount;
pattern = Pattern.compile(regexp);
}
public boolean fit(String str)
{
int count = str.length() - pattern.matcher(str).replaceAll("").length();
return count >= mincount && count <= maxcount;
}
#Override
public String toString() {
return pattern.toString();
}
}
public class Test {
static Constraint[] constraints = new Constraint[] {
new Constraint("[a-z]",2,20),
new Constraint("[A-Z]",2,20),
new Constraint("\\d",2,20),
new Constraint("["+Pattern.quote("##$%!##%&*?_~,-")+"]",2,20),
new Constraint("[<>'\\\"]",0,0)
};
public static boolean checkit(String pwd)
{
boolean ok=true;
for (Constraint constraint:constraints)
{
if (constraint.fit(pwd)==false)
{
System.out.println("match failed for constraint "+constraint);
ok=false;
}
}
return ok;
}
public static void main(String[] args) {
checkit("23aaAAA#!");
checkit("a2#!AAAa");
}
}
I am trying to mask the SSN which is in "123-12-1234" to "XXX-XX-1234". I am able achieve using the below code.
string input = " 123-12-1234 123-11-1235 ";
Match m = Regex.Match(input, #"((?:\d{3})-(?:\d{2})-(?<token>\d{4}))");
while (m.Success)
{
if (m.Groups["token"].Length > 0)
{
input = input.Replace(m.Groups[0].Value,"XXX-XX-"+ m.Groups["token"].Value);
}
m = m.NextMatch();
}
Is there a better way to do it in one line using the Regex.Replace method.
You can try the following:
string input = " 123-12-1234 123-11-1235";
string pattern = #"(?:\d{3})-(?:\d{2})-(\d{4})";
string result = Regex.Replace(input, pattern, "XXX-XX-$1");
Console.WriteLine(result); // XXX-XX-1234 XXX-XX-1235
If your are going to be doing a lot of masking you should consider a few whether to use compiled regular expression or not.
Using them will cause a slight delay when the application is first run, but they will run faster subsequently.
Also the choice of static vs instances of the Regex should be considered.
I found the following to be the most efficient
public class SSNFormatter
{
private const string IncomingFormat = #"^(\d{3})-(\d{2})-(\d{4})$";
private const string OutgoingFormat = "xxxx-xx-$3";
readonly Regex regexCompiled = new Regex(IncomingFormat, RegexOptions.Compiled);
public string SSNMask(string ssnInput)
{
var result = regexCompiled.Replace(ssnInput, OutgoingFormat);
return result;
}
}
There is a comparison of six methods for regex checking/masking here.
I have two vectors, one which holds my regular expressions and one which holds the string in which will be checked against the regular expression, most of them work fine except for this one (shown below) the string is a correct string and matches the regular expression but it outputs incorrect instead of correct.
INPUT STRING
.C/IATA
CODE IS BELOW
std::string errorMessages [6][6] = {
{
"Correct Corparate Name\n",
},
{
"Incorrect Format for Corporate Name\n",
}
};
std::vector<std::string> el;
split(el,message,boost::is_any_of("\n"));
std::string a = ("");
for(int i = 0; i < el.size(); i++)
{
if(el[i].substr(0,3) == ".C/")
{
DCS_LOG_DEBUG("--------------- Validating .C/ ---------------");
output.push_back("\n--------------- Validating .C/ ---------------\n");
str = el[i].substr(3);
split(st,str,boost::is_any_of("/"));
for (int split_id = 0 ; split_id < splitMask.size() ; split_id++ )
{
boost::regex const string_matcher_id(splitMask[split_id]);
if(boost::regex_match(st[split_id],string_matcher_id))
{
a = errorMessages[0][split_id];
DCS_LOG_DEBUG("" << a )
}
else
{
a = errorMessages[1][split_id];
DCS_LOG_DEBUG("" << a)
}
output.push_back(a);
}
}
else
{
DCS_LOG_DEBUG("Do Nothing");
}
st[split_id] = "IATA"
splitMask[split_id] = "[a-zA-Z]{1,15}" <---
But it still outputs Incorrect format for corporate name
I cannot see why it prints incorrect when it should be correct can someone help me here please ?
Your regex and the surrounding logic is OK.
You need to extend your logging and to print the relevant part of splitMask and st right before the call to boost::regex_match to double check that the values are what you believe they are. Print them surrounded in some punctuation and also print the string length to be sure.
As you probably know, boost::regex_match only finds a match if the whole string is a match; therefore, if there is a non-printable character somewhere, or maybe a trailing space character, that will perfectly explain the result you have seen.