Powershell specific character not match for function - regex

Am trying to create a filter to only run the IF clause in case of the character in the 4 position be either "W", "X", "Y", "Z".
The code so far looks like this:
$name= "123Y567"
if ($name.notcontains("Y"))
{
"Action 1"
}
else
{
"Action 2"
}
}
I have tried this as well
$name= "123Y567"
if ($name -notmatch (/^.{4}["Y"]/))
{
"Action 1"
}
else
{
"Action 2"
}
}
What could be the best solution for this? but new working with scripting and Powershell in general.

Without regex, as Lee_Daily already suggested, use switch on the 4th character:
$name= "123Y567"
switch ($name[3]) {
'W' { Action_1 }
'X' { Action_2 }
'Y' { Action_3 }
'Z' { Action_4 }
}
Or if the action to perform is the same for any of the characters 'W','X','Y','Z' :
$name= "123Y567"
if ('W','X','Y','Z' -contains $name[3] ) { Action_1 }

If you want to use regex to check if the fourth char is a char in a custom range/set you may use
if ($name -cmatch '^.{3}[W-Z]')
Note that PS regex matching is case insensitive with -match, you need to use -cmatch to make it case sensitive.
The pattern matches
^ - start of string
.{3} - any 3 chars other than a newline
[W-Z] - a W, X, Y or Z.

Related

Powershell SWITCH and REGEX

Hi can anybody help me I am stuck and can't get regex to work with powershell and a switch statement.
Could not find anything on the web that was helpful either.
How can I filter an IP for example or a string of 7 to 8 numbers?
switch -regex ($buffer)
{
($buffer -match '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
{}
($buffer -match {'\d{7,8}'})
{}
}
When used in -regex mode, PowerShell expects the case condition to be a regex pattern, nothing else:
switch -regex ($buffer)
{
'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
{
# looks kinda like an IP
}
'\d{7,8}'
{
# just numbers
}
}
Use braces instead of parenthesis, and omit the variable for switch altogether:
switch (1)
{
{ $buffer -match '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' }
{ Write-Output "IP Address" }
{ $buffer -match '\d{7,8}' }
{ Write-Output "7-8 digits" }
}

Conditional If with REGEX

I'm working on a function to try some regex. Let me explain.
function traitement
{
if ($Matches.NAME -match "^A_(?<test1>[\w{1,6}]{1,7})")
{
[void]($memberOfCollection.add($Matches.test1))
}
elseif ($Matches.NAME -match "^A_(?<test2>[]*)")
{
[void]($memberOfCollection.add($Matches.test2))
}
else
{
[void]($memberOfCollection.add($Matches.NAME))
}
}
I have $Matches.NAME return string like "A_UserINTEL", "A_UserINTELASUS" or "A_UserINTEL_Adobe"
I need to differentiate 2 strings coming from $Matches.NAME and therefore write several tests.
"A_UserINTEL" and "A_UserINTELASUS" must return "UserINTEL".
"A_UserINTEL_Adobe" must return "UserINTEL_Adobe"
Test1 allows me to retrieve "UserINTEL" but I didn't succeed test2 to bring me "UserINTEL_Adobe".
Any idea? Thank you.
There's a;ways more ways then just one, especially when it comes to regular expressions, but here's one way:
function traitement {
# just for more clarity in the rest of the code
$name = $Matches.NAME
if ($name -match '^A_UserIntel(?:ASUS)?$') {
# the regex tests for "A_UserINTEL" or "A_UserINTELASUS"
[void]($memberOfCollection.add("UserINTEL"))
}
elseif ($name -match '^A_UserIntel_Adobe$') {
# this elseif is basically the same as
# elseif ($name -eq 'A_UserIntel_Adobe') {
# no real need for regex there..
[void]($memberOfCollection.add("UserINTEL_Adobe"))
}
else {
[void]($memberOfCollection.add($name))
}
}

regex validating telephone number, but chops white space using perl

So I have an HTML field in a form that takes in a phone number. It validates it correctly when I use () or / or - however, if I put in say 555 123 4567, it returns 555. As always your help is greatly appreciates it.
Here is my code
my $userName=param("userName");
my $password=param("password");
my $phoneNumber=param("phoneNumber");
my $email=param("email");
my $onLoad=param("onLoad");
my $userNameReg = "[a-zA-Z0-9_]+";
my $passwordReg = "([a-zA-Z]*)([A-Z]+)([0-9]+)";
my $phoneNumberReg = "((\(?)([2-9]{1}[0-9]{2})(\/|-|\)|\s)?([2-9]{1}[0-9]{2})(\/|-|\s)?([0-9]{4}))";
my $emailReg = "([a-zA-Z0-9_]{2,})(#)([a-zA-Z0-9_]{2,})(.)(com|COM)";
if ($onLoad !=1)
{
#controlValue = ($userName, $password, $phoneNumber, $email);
#regex = ($userNameReg, $passwordReg, $phoneNumberReg, $emailReg);
#validated;
for ($i=0; $i<4; $i++)
{
$retVal= validatecontrols ($controlValue[$i], $regex[$i]);
if ($retVal)
{
$count++;
}
if (!$retVal)
{
$validated[$i]="*"
}
}
sub validatecontrols
{
my $ctrlVal = shift();
my $regexVal = shift();
if ($ctrlVal =~ /^$regexVal$/)
{
return 1;
}
return 0;
}
}
*html code is here*
I realize that this is part of an assignment, so you may be working under specific restraints. However, your attempt to abstract out your data validation is honestly just making things messy and harder to follow. It also ties you down to specifically regex tests, which may not actually be the best bet. As has already been said, email validation should be done via a module.
Also, for this phone validation, an easier solution is just to strip out anything that isn't a number, and then do your validation test. The below code demonstrates what I'm talking about:
my $userName = param("userName");
my $password = param("password");
my $phoneNumber = param("phoneNumber");
my $email = param("email");
my $onLoad = param("onLoad");
my $error = 0;
if ($onLoad !=1)
{
if ($username !~ /^[a-zA-Z0-9_]+$/) {
$username = '*';
$error++;
}
if ($password !~ /^[a-zA-Z]*[A-Z]+[0-9]+$/) {
$password = '*';
$error++;
}
(my $phoneNumOnly = $phoneNumber) =~ s/\D//g;
if ($phoneNumOnly !~ /^1?[2-9]{1}\d{2}[2-9]{1}\d{6}$/) {
$phoneNumber = '*';
$error++;
}
if ($email !~ /^\w{2,}\#\w{2,}\.com$/i) {
$email = '*';
$error++;
}
}
*html code is here*
That regex you're using looks a overly complicated. You have a lot of capturing groups in there, but I get the feeling you're mostly using them to define "OR" statements with the vertical bar. It's usually a lot easier to just use brackets for this purpose if you're only selecting single characters. Also, it's not a good idea to use\s for normal spaces, since this will actually match any whitespace character (tabs and newlines). Maybe try something like this:
(?:\(?[2-9]\d{2}\)?[-\/ ]?)?[2-9]\d{2}[-\/ ]?\d{4}

Perl argument switch based on regex

I have a Perl script that takes in arguments. When I had single value arguments, the following code sufficed:
switch ($ARGV[0]) {
case "--cmd1" {
$action = "cmd1";
}
case "--cmd2" {
$action = "cmd2";
}
Now, I have a case where the command, cmd3 has a parameter, as in --cmd3=SOMETHING. Since SOMETHING can vary, the simple switch/case does not work anymore. Basically, I need to do a switch/case on the command itself. I thought I could use a regex with the first matching group being the command and the second being the optional equals. The following does not work, but it illustrates what I'm trying to do.
$ARGV[0] =~ m/(.*?)(=.*){0,1}/;
my $cmd = $1;
my $equals = $2;
switch ($cmd) {
case "--cmd1" {
$action = "cmd1";
}
case "--cmd2" {
$action = "cmd2";
}
case "--cmd3" {
$action = "cmd3";
print $equals;
}
:::::::::::::::::::::::::::::::::::EDIT:::::::::::::::::::::::::::::::::::::::::::::::::::::
I figured it out, but I'll give the guy who answered upvotes and accept anyway. I could not use if because that means restructuring everything. Here's the solution.
switch ($ARGV[0]) {
case "--cmd1" {
$action = "cmd1";
}
case "--cmd2" {
$action = "cmd2";
}
case m/--cmd3(=.*)?/ {
$ARGV[0] =~ m/--cmd3(=.*)?/;
$action = "cmd3";
print $1;
}
Why aren't you using Getopt::Long?
How about something like this?
my $cmd = "";
my $equals = "";
if($ARGV[0] =~ m/^\-\-cmd1$/){$cmd="cmd1"}
if($ARGV[0] =~ m/^\-\-cmd2$/){$cmd="cmd2"}
if($ARGV[0] =~ m/^\-\-cmd3=(.*)$/){$cmd="cmd3";$equals=$1}

Perl Regex not matching

I'm trying to match lines from a file and extract a certain part.
My Regex works with all online testers I could find but not with my perl.
I'm on version v5.10.0 and cannot update.
The regex looks like this:
sub parse_bl_line {
if ($_[0] =~ m/^copy\s+.*?\s+(.*?\_.*)/) {
return $1;
} else {
log_msg("Line discarded: $_[0]", 4);
return "0";
}
}
A couple lines of test data which should match (only the last matches):
#bl_lines = (
"copy xxxxxx_/cpu b_relCAP_R3.0-1_INT5_xxxxx_cpu_p1",
"copy xxxxxxxx_/va_xxx_parameters b_relCAP_R3.0-1_INT5_xxxxx_va_xxx_parameters_p1",
"copy xxxxxxxx_/xxxxxxx_view.tcl b_relCAP_R3.0-1_INT5_xxxxxx_view.tcl_p0",
"copy xxxxx_/xxxxxarchivetool.jar b_relEARLY_DROP1_xxxxxarchivetool.jar_xx");
And calling the function:
foreach(#bl_lines) {
$file=parse_bl_line($_);
if ($file !~ "0") {
log_msg("Line accepted: $_", 4);
log_msg("File extracted: $file", 4);
}else {
log_msg("Line rejected: $_", 2);
}
}
I'm trying to match the last part e.g.
b_relEARLY_DROP1_xxxxxarchivetool.jar_xx
Output looks the following:
20120726 13:15:34 - [XXX] ERROR: Line rejected: copy xxxxxx_/cpu b_relCAP_R3.0-1_INT5_xxxxx_cpu_p1
20120726 13:15:34 - [XXX] ERROR: Line rejected: copy xxxxxxxx_/va_xxx_parameters b_relCAP_R3.0-1_INT5_xxxxx_va_xxx_parameters_p1
20120726 13:15:34 - [XXX] ERROR: Line rejected: copy xxxxxxxx_/xxxxxxx_view.tcl b_relCAP_R3.0-1_INT5_xxxxxx_view.tcl_p0
20120726 13:15:35 - [XXX] INFO: Line accepted: copy xxxxx_/xxxxxarchivetool.jar b_relEARLY_DROP1_xxxxxarchivetool.jar_xx
20120726 13:15:35 - [XXX] INFO: File extracted: b_relEARLY_DROP1_xxxxxarchivetool.jar_xx
Hint
I did some of the testing that #BaL proposed and found out that the pattern matching works without the selection parenthesis.
if ($_[0] =~ m/^copy\s+.+?\s+.+?\_.+$/) {
The test : if ($file !~ "0") { is true when $file doesn't contain a 0 at any position which is the case of the last string only.
I guess you want to use : if ($file ne '0') { or even shorter : if ($file) {
Apart of this you should really use strict; and use warnings always.
What are you trying to match ? The last part ?
Don't use * if you know that you have something to match, use + instead :
if ($_[0] =~ m/^copy\s+.+?\s+(.\+?)$/) {
return $1;
}
I'm guessing that the last line of your test file is the only one that doesn't end with a "\n". Funny little buggers are always getting in the way.....
Change the comparison operator in your if statement from !~ to ne as you are making a string comparison. When I make this change, all log lines were accepted.
I tested this on perl 5.14.2, not 5.10, but I didn't use any special features. Give it a go! code is below:
use 5.14.2;
sub log_msg{
say shift;
}
sub parse_bl_line {
if ($_[0] =~ m/^copy\s+.*?\s+(.*?\_.*)/) {
return $1;
}
else {
log_msg("Line discarded: $_[0]", 4);
return "0";
}
}
my #bl_lines = (
"copy xxxxxx_/cpu b_relCAP_R3.0-1_INT5_xxxxx_cpu_p1",
"copy xxxxxxxx_/va_xxx_parameters b_relCAP_R3.0-1_INT5_xxxxx_va_xxx_parameters_p1",
"copy xxxxxxxx_/xxxxxxx_view.tcl b_relCAP_R3.0-1_INT5_xxxxxx_view.tcl_p0",
"copy xxxxx_/xxxxxarchivetool.jar b_relEARLY_DROP1_xxxxxarchivetool.jar_xx"
);
foreach(#bl_lines) {
my $file = parse_bl_line($_);
if ($file ne "0") { # Changed the comparison operator here
log_msg("Line accepted: $_", 4);
log_msg("File extracted: $file", 4);
}
else {
log_msg("Line rejected: $_", 2);
}
}