Can I "combine" 2 regex with a logic or? - regex

I need to validate Textbox input as credit card number. I already have regex for different credit cards:
Visa: ^4[0-9]{12}(?:[0-9]{3})?$
Mastercard: ^([51|52|53|54|55]{2})([0-9]{14})$
American Express: ^3[47][0-9]{13}$
and many others.
The problem is, I want to validate using different regex based on different users. For example: For user1, Visa and Mastercard are available, while for user2, Visa and American Express are available. So I would like to generate a final regex string dynamically, combining one or more regex string above, like:
user1Regex = Visa regex + "||" + Mastercard regex
user2Regex = Visa regex + "||" + American Express regex
Is there a way to do that? Thanks,

You did not state your language but for whatever reason I suspect it's JavaScript. Just do:
var user1Regex = new RegExp('(' + Visaregex + ")|(" + Mastercardregex + ')');
// or if es6:
let user1Regex = new RegExp(`(${Visaregex})|(${Mastercardregex})`);
You can also use (?:) for speedier execution (non-capturing grouping) but I have omitted that for readability.

Use the | operator and group all with parentesis ()
^(4[0-9]{12}(?:[0-9]{3})?|([51|52|53|54|55]{2})([0-9]{14})|3[47][0-9]{13})$
If all regex are correct it should work

Not sure which language you are using to implement but you can use a single | to use a logical or most regex. My suggestion would be to store each regex as a string and then concatenate and compile when necessary.
in python it would be something like
visa = "visa_regex"
mastercard = "mastercard_regex"
combined = re.compile(visa + "|" + mastercard)

combine two expressions or more, put every expression in brackets,
and use: *?
This are the signs to combine, in order of relevance:
*? example 1 : (A)*?(B)
| example 2 : A|B
()() example 3 : (A)(B)
()|() example 4 : (A)|(B)

Related

Regex pattern for number or three letters

I need to sort a table field with different kind of values:
number from 0 to 999+
group of three letters like AAA, AAB, AAC, AAD, etc.
StupidTable.js enables me to add a custom alphanumeric data type, but i'm not able to define the regex pattern.
I tried this code:
$("table").stupidtable({
"alphanum":function(a,b){
console.log(a,b)
var pattern = "^[a-zA-Z0-9_.-]*$";
var re = new RegExp(pattern);
var aNum = re.exec(a).slice(1);
var bNum = re.exec(b).slice(1);
return parseInt(aNum,10) - parseInt(bNum,10);
}
})
but it doesnt work. You can check the issue on this page clicking on "nr" tab: Test
Try something like this:
const regexPattern = /^[\d\w]{3}/gm;
This pattern allows you to capture a string if it contains only a 3 digit number or a 3 letter code. If you want to capture 0 and not 000, you will need to change {3} with {1,3}, but this will also capture A instead of AAA.
You might also consider normalizing your data in some ways, e.g. converting A to AAA and 0 to 000. This could be helpful for a number of reasons assuming your variable type is a string and not actually a number type. Does that make sense?
You can see how I've created this pattern at the link below, and try some tweaks to make it work well for you. I use this tool a lot and it will also generate some code for you in different languages. Good luck with your project, let me know how it goes.
Regex101.com

How to convert a regex pattern that uses Lookahead?

I'm having trouble converting this regex to something Golang supports. Could I get some help? It's originally from this SO question.
^(?=.{1,24}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$
Here's the criteria:
Only contains alphanumeric characters,
underscore and dot.
Underscore and dot can't be at the end or
start of a username (e.g _username / username_ / .username / username.).
Underscore and dot can't be next to each other (e.g user_.name).
Underscore or dot can't be used multiple times in a row (e.g user__name / user..name).
I don't have any experience with Go, so perhaps someone could come up with a better solution.
Here are the two options I found:
1. Write a regex that covers everything except the length restriction
You can use something like this:
^(?:[a-zA-Z0-9]+[._]?[a-zA-Z0-9]+)+$
Regex101 demo.
And you can use len to check for the string length. Here's a full example:
func main() {
var re = regexp.MustCompile(`(?m)^(?:[a-zA-Z0-9]+[._]?[a-zA-Z0-9]+)+$`)
var str = `username
user_name
user.name
user.name_123
username$$$
_username
username_
user_.name
user._name
user__name
user..name
VeryLongUserNameThatExceedsTheLimit
`
for i, match := range re.FindAllString(str, -1) {
if len(match) <= 24 {fmt.Println(match, "found at index", i)}
}
}
Output:
username found at index 0
user_name found at index 1
user.name found at index 2
user.name_123 found at index 3
Test it online.
2. Use a third-party engine
I found this .NET-based engine which should support Lookarounds. If the previous solution doesn't work for you, you may look into this. Note that the author of that engine recommends using the built-in engine whenever possible:
You'll likely be better off with the RE2 engine from the regexp
package and should only use this if you need to write very complex
patterns or require compatibility with .NET.

A single Regex Match Entire String first to then break up into multiple components

I am trying to come up with a RegEx (POSIX like) in a vendor application that returns data looking like illustrated below and presents a single line of data at a time so I do not need to account for multiple rows and need to match a row indvidually.
It can return one or more values in the string result
The application doesn't just let me use a "\d+\.\d+" to capture the component out of the string and I need to map all components of a row of data to a variable unfortunately even if I am going to discard it or otherwise it returns a negative match result.
My data looks like the following with the weird underscore padding.
USER | ___________ 3.58625 | ___________ 7.02235 |
USER | ___________ 10.02625 | ___________ 15.23625 |
The syntax is supports is
Matches REGEX "(Var1 Regex), (Var2 Regex), (Var3 Regex), (Var 4 regex), (Var 5 regex)" and the entire string must match the aggregation of the RegEx components, a single character off and you get nothing.
The "|" characters are field separators for the data.
So in the above what I need is a RegEx that takes it up to the beginning of the numeric and puts that in Var1, then capture the numeric value with decimal point in var 2, then capture up to the next numeric in Var 3, and then keep the numeric in var 4, then capture the space and end field | character into var 5. Only Var 2 and 4 will be useful but I have to capture the entire string.
I have mainly tried capturing between the bars "|" using ^.*\|(.*).\|*$ from this question.
I have also tried the multiple variable ([0-9]+k?[.,]?[0-9]+)\s*-\s*.*?([0-9]+k?[.,]?[0-9]+) mentioned in this question.
I seem to be missing something to get it right when I try using them via RegExr and I feel like I am missing something pretty simple.
In RegExr I never get more than one part of the string I either get just the number, the equivalent of the entire string in a single variable, or just the number which don't work in this context to accomplish the required goal.
The only example the documentation provides is the following from like a SysLog entry of something like in this example I'm consolidating there with "Fault with Resource Name: Disk Specific Problem: Offline"
WHERE value matches regex "(.)Resource Name: (.), Specific Problem: ([^,]),(.)"
SET _Rrsc = var02
SET _Prob = var03
I've spun my wheels on this for several hours so would appreciate any guidance / help to get me over this hump.
Something like this should work:
(\D+)([\d.]+)(\D+)([\d.]+)(.*)
Or in normal words: Capture everything but numbers, capture a decimal number, capture everything but numbers, capture a decimal number, capture everything.
Using USER | ___________ 10.02625 | ___________ 15.23625 |
$1 = USER | ___________  
$2 = 10.02625
$3 =  | ___________  
$4 = 15.23625
$5 =  |

Regexp to match only n occurrences of a char in a string

I have a string like 2005:10:29 12:23:53 and I wish to replace only first two occurrences of : with -
Expected result 2005-10-29 12:23:53
EDIT:
I need this regexp in KDE's krename tool, where I can't edit/format the original [exifExif.Image.DateTime] witch returns the unwanted 2005:10:29 12:23:53 format, but there is a Find and Replace to post process the String
(?<=\d{4}):|:(?=\d{2}\s) does the job on rubular, but does not in KDE :(
I am sure there are more solutions.
EDIT:
:(?=\d{2}:\d{2}\s)|:(?=\d{2}\s) works even on KDE
I find this solution after I read
You can use a full-fledged regular expression inside the lookahead.
Most regular expression engines only allow literal characters and
alternation inside lookbehind, since they cannot apply regular
expression backwards.
in Regex tutorial
In Ruby, as scibuff suggests, you're probably better not using Regexps.
require 'date'
date = DateTime.parse("2005:10:29 12:23:53", "%Y:%m:%d %H:%M:%S")
date.strftime("%Y-%m-%d %H:%M:%S")
JavaScript:
Version 1
str = str.split(' ')[0].replace(/\:/g,'-')+' '+str.split(' ')[1]
Version 2
str = str.replace(/(\d{4}):(\d{2}):(\d{2})(.*)/,"$1-$2-$3 $4")
DEMO
Once again using regular expressions for something that can be achieved in a simpler, more elegant and more efficient way
var date = new Date('2005:10:29 12:23:53');
then format date accordingly, e.g.
function formatDate( date ){
return date.getFullYear() + '-' + ( get.getMonth() + 1 ) + '-' + ... ;
}
Simply call replace() twice:
"2005:10:29 12:23:53".replace(/:/,'-').replace(/:/,'-')

Regex to replace string with another string in MS Word?

Can anyone help me with a regex to turn:
filename_author
to
author_filename
I am using MS Word 2003 and am trying to do this with Word's Find-and-Replace. I've tried the use wildcards feature but haven't had any luck.
Am I only going to be able to do it programmatically?
Here is the regex:
([^_]*)_(.*)
And here is a C# example:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
String test = "filename_author";
String result = Regex.Replace(test, #"([^_]*)_(.*)", "$2_$1");
}
}
Here is a Python example:
from re import sub
test = "filename_author";
result = sub('([^_]*)_(.*)', r'\2_\1', test)
Edit: In order to do this in Microsoft Word using wildcards use this as a search string:
(<*>)_(<*>)
and replace with this:
\2_\1
Also, please see Add power to Word searches with regular expressions for an explanation of the syntax I have used above:
The asterisk (*) returns all the text in the word.
The less than and greater than symbols (< >) mark the start and end
of each word, respectively. They
ensure that the search returns a
single word.
The parentheses and the space between them divide the words into
distinct groups: (first word) (second
word). The parentheses also indicate
the order in which you want search to
evaluate each expression.
Here you go:
s/^([a-zA-Z]+)_([a-zA-Z]+)$/\2_\1/
Depending on the context, that might be a little greedy.
Search pattern:
([^_]+)_(.+)
Replacement pattern:
$2_$1
In .NET you could use ([^_]+)_([^_]+) as the regex and then $2_$1 as the substitution pattern, for this very specific type of case. If you need more than 2 parts it gets a lot more complicated.
Since you're in MS Word, you might try a non-programming approach. Highlight all of the text, select Table -> Convert -> Text to Table. Set the number of columns at 2. Choose Separate Text At, select the Other radio, and enter an _. That will give you a table. Switch the two columns. Then convert the table back to text using the _ again.
Or you could copy the whole thing to Excel, construct a formula to split and rejoin the text and then copy and paste that back to Word. Either would work.
In C# you could also do something like this.
string[] parts = "filename_author".Split('_');
return parts[1] + "_" + parts[0];
You asked about regex of course, but this might be a good alternative.