powershell regex and e.164 - regex

In powershell, I'm trying to create a E.164 type regex for a number of countries. I explicitly need to have the (+) plus in my number and in most cases multi number country codes.
For some reason: '+421233339135' does not match '/^(\+[4][2][1])?([1-9]\d\d{7})$'
+421 is the country code, the first digit after the CC needs to be between 1-9, the rest can be any number then 9 digits afterwards is the DID number.
hope someone can help:-)

For some reason: '+421233339135' does not match '/^(\+[4][2][1])?([1-9]\d\d{7})$'
PowerShell is not Perl, a leading / before the pattern is not expected - remove it.
The pattern itself could be described simply as ^(\+421)?([1-9]\d{8})$
PS C:\> $phoneNumber = '+421233339135'
PS C:\> $phoneNumber -match '^(\+421)?([1-9]\d{8})$'
True

Related

Regex for valid SSN or other ID

I'm a regex newbie and I've got a valid regex for SSNs:
/^(\d{3}(\s|-)?\d{2}(\s|-)?\d{4})|[\d{9}]*$/
But I now need to expand it to accept either an SSN or another alphanumeric ID of 7 characters, like this:
/^[a-zA-Z0-9]{7}$/
I thought it'd be as simple as grouping the SSN and adding an OR | but my tests are still failing. This is what I've got now:
/^((\d{3}(\s|-)?\d{2}(\s|-)?\d{4})|[\d{9}])|[a-zA-Z0-9]{7}$/
What am I doing wrong? And is there a more elegant way to say either SSN or my other ID?
Thanks for any helpful tips.
Valid SSNs:
123-45-6789
123456789
123 45 6789
Valid ID: aCe8999
I have modified your first regex also a bit, below is demo program. This is as per my understanding of the problem. Let me know if any modification is needed.
my #ids = (
'123-45-6789',
'123456789',
'123 45 6789',
'1234567893434', # invalid
'123456789wwsd', # invalid
'aCe8999',
'aCe8999asa' # invalid
);
for (#ids) {
say "match = $&" if $_ =~ /^ (?:\d{3} ([ \-])? \d{2} \1? \d{4})$ | ^[a-zA-Z0-9]{7}$/x ;
}
Output:
match = 123-45-6789
match = 123456789
match = 123 45 6789
match = aCe8999
Your first regex got some problems. The important thing about it is that it accepts {{{{}}}}} which means you have built a wrong character class. Also it matches 123-45 6789 (notice the mixture of space and dash).
To mean OR in regular expressions you need to use pipe | and remember that each symbol belongs to the side that it resides. So for example ^1|2$ checks for strings beginning with 1 or ending with 2 not only two individual input strings 1 and 2.
To apply the exact match you need to do ^1$|^2$ or ^(1|2)$.
With the second regex ^[a-zA-Z0-9]{7}$ you are not saying alphanumeric ID of 7 characters but you are saying numeric, alphabetic or alphanumeric. So it matches 1234567 too. If this is not a problem, the following regex is the solution by eliminating the said issues:
^\d{3}([ -]?)\d\d\1\d{4}$|^[a-zA-Z0-9]{7}$

bash regular expression that will match YYMMDD but not longer numbers

The general problem
I am trying to understand how to prevent the existence of some pattern before or after a sought-out pattern when writing regex's!
A more specific example
I'm looking for a regex that will match dates in the format YYMMDD ((([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]))) inside a long string while ignoring longer numeric sequences
it should be able to match:
text151124moretext
123text151124moretext
text151124
text151124moretext1944
151124
but should ignore:
text15112412moretext
(reason: it has 8 numbers instead of 6)
151324
(reason: it is not a valid date YYMMDD - there is no 13th month)
how can I make sure that if a number has more than these 6 digits, it won't picked up as a date inside one single regex (meaning, that I would rather avoid preprocessing the string)
I've thought of \D((19|20)([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]))\D but doesn't this mean that there has to be some character before and after?
I'm using bash 3.2 (ERE)
thanks!
Try:
#!/usr/bin/env bash
extract_date() {
local string="$1"
local _date=`echo "$string" | sed -E 's/.*[^0-9]([0-9]{6})[^0-9].*/\1/'`
#date -d $_date &> /dev/null # for Linux
date -jf '%y%m%d' $_date &> /dev/null # for MacOS
if [ $? -eq 0 ]; then
echo $_date
else
return 1
fi
}
extract_date text15111224moretext # ignore n_digits > 6
extract_date text151125moretext # take
extract_date text151132 # # ignore day 32
extract_date text151324moretext1944 # ignore month 13
extract_date text150931moretext1944 # ignore 31 Sept
extract_date 151126 # take
Output:
151125
151126
If your tokens are line-separated (i.e. there is only one token per line):
^[\D]*[\d]{6}([\D]*|[\D]+[\d]{1,6})$
Basically, this regex looks for:
Any number of non-digits at the beginning of the string;
Exactly 6 digits
Any number of non-digits until the end OR at least one non-digit and at least one digit (up to 6) to the end of the string
This regex passes all of your given sample inputs.
You could use non-capturing groups to define non-digits either side of your date Regex. I had success with this expression and your same test data.
(?:\D)([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])(?:\D)

How can I identify a number of variable length with a regex?

I need a Perl regex to pull a number of between six and ten digits out of a string. The number will always follow a particular word followed by a space (case unknown).
For example, if the word I was looking for is 'string':
some random text blah blah blahSTRING 1234567890some more random text
Desired output:
1234567890
Another example:
yet more random textra ra rastring 654321hey hey my my
Desired output:
654321
I want to load the result into a variable.
/string ([0-9]{6,10})/i
string matches STRING and string as the expression ends with i (case insenstive matching)
matches a space
(starts a capture group to capture the number you trying to get
[0-9]{6,10}matches a number with 6 to 10 places
https://regex101.com/r/mB1zF4/1
Group 1 should contain your number with
/^.*string (\d+).*$/i
Thanks everyone, between all the responses and a bit of googling I ended up with
#!/usr/local/bin/perl -w
use strict;
my $string = 'sgtusadl;fdsas;adlhstring 12345678daf;slkdfja;dflk';
my ( $number ) = $string =~ m/string\s\d{6,10}/gi;
$number =~ s/[^0-9]//g;
print "number is $number\n";
exit 0;

grep regex unexpected match - literal matches against number

Why does the following literal string
1998-${year}
..match against the grep command:
grep "[0-9 ]*-[ 0-9]*" filename.txt ?
What I need is a regex to match any of the following strings containing either a year range or one value of year only.
sdkfmslf 1998-2008
asdassdadsa 1998 - 2008
mkklml mklsmdf 2006
..but NOT this one:
asdsad a s 1998-${year}
* means "match zero or more". You want + which means "one or more."
grep "[0-9 ]+-[0-9]+" filename.txt
Try [0-9]{4}(\s*-\s*[0-9]{4})?. This will match a 4 digit number, or if it is followed by (optional white space)-(optional whitespace) then that must be followed by another 4 digit number.
Your string "asdsad a s 1998-${year}" would still match, since it has a single 4 digit value in it.
I don't like answering my own question, but none of the above worked. Here is what I found by experimenting. I'm sure there could be more elegant solutions, but here is a working version:
grep "[0-9][0-9][0-9][0-9][ ]*[\-]*[ ]*[0-9]*" filename.txt

Regex match and grouping

Here's a sample string which I want do a regex on
101-nocola_conte_-_fuoco_fatuo_(koop_remix)
The first digit in "101" is the disc number and the next 2 digits are the track numbers. How do I match the track numbers and ignore the disc number (first digit)?
Something like
/^\d(\d\d)/
Would match one digit at the start of the string, then capture the following two digits
Do you mean that you don't mind what the disk number is, but you want to match, say, track number 01 ?
In perl you would match it like so: "^[0-9]01.*"
or more simply "^.01.*" - which means that you don't even mind if the first char is not a digit.
^\d(\d\d)
You may need \ in front of the ( depending on which environment you intend to run the regex into (like vi(1)).
Which programming language? For the shell something with egrep will do the job:
echo '101-nocola_conte_-_fuoco_fatuo_(koop_remix)' | egrep -o '^[0-9]{3}' | egrep -o '[0-9]{2}$'