powershell search function with regular expression - powershell

the text file content is:
In this script, we have the following variables:
$input_path to hold the path to the input file we want to parse
$output_file to hold the path to the file we want the results to be stored in
$regex to hold the regular expression pattern to be used when the strings are being matched.
The select-string cmdlet contains various parameters as follows:
-Path which takes as input the full path to the input file
-Pattern which takes as input the regular expression used in the matching process
AllMatches which searches for more than one match (without this parameter it would stop after the first match is found) and is piped to $.Matches and then $_.Value which represent using the current values of all the matches.
Code:
$replace_file=#{}
$replace_text_file_path="EMS_checksystem_script\replace.txt"
$replace_file= gc $replace_text_file_path
$result=0
$valr=read-host "please enter the key word"
for($i=0;$i -lt$file_context.length;$i++)
{
$result=$replace_file[$i] -match $valr
if( $result -eq 1)
{
$replace_file[$i]
}
}
Result:
key word: *pression
Bad argument to operator '-match': parsing "*pression" - Quantifier {x,y} following nothing..
At line:11 char:37
+ $result=$replace_file[$i] -match <<<< '*pression'
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : BadOperatorArgument
key word: pression*
key word: press*on
NO result
How can use the press*on and *pression keywords to search?

Read up on regex. You can test regex here > http://www.regexr.com/
Your keyword is wrong, use "." to match any character and "*" to match any number of the previous character.
PS C:\>'expression' -match ".*pression"
PS C:\>True

Related

How to assign and reference environment variables containing square brackets in Powershell

When the PSDrive is not specified, the following works:
${[foo]}="bar"
echo ${[foo]}
But the following does not work
$env:${[foo]}="bar"
At line:1 char:1
+ $env:${[foo]}="bar"
+ ~~~~~
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to delimit the name.
At line:1 char:6
+ $env:${[foo]}="bar"
+ ~~~~~~~~~~~~~~
Unexpected token '${[foo]}="bar"' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidVariableReferenceWithDrive
${env:[foo]}="bar"
Cannot find path 'env:[foo]' because it does not exist.
At line:1 char:1
+ ${env:[foo]}="bar"
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (env:[foo]:String) [], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound
The following works, though I am curious if there's short hand syntax for it:
Set-Item -LiteralPath env:${[foo]} -Value "bar"
Get-Item -LiteralPath env:${[foo]} | % {$_.Value}
However the following does not work:
Set-Item -LiteralPath env:${[foo]2} -Value "bar"
Set-Item : Cannot process argument because the value of argument "name" is null. Change the value of argument "name" to a non-null value.
At line:1 char:1
+ Set-Item -LiteralPath env:${[foo]2} -Value "bar"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:String) [Set-Item], PSArgumentNullException
+ FullyQualifiedErrorId : SetItemNullName,Microsoft.PowerShell.Commands.SetItemCommand
Written as of PowerShell Core 6.2.0
The reason is that PowerShell treats the following:
${<drive>:<name>}
as if you had specified:
Get-Content -Path <drive>:<name> # or, with assignment, Set-Content -Path ...
This notation - though often used with the Env: drive (e.g., $env:Path) - is little-known as a general paradigm named namespace variable notation, which is explained in this answer.
The problem is the use of -Path rather than -LiteralPath, because -Path interprets its argument as a wildcard expression.
Therefore, the [foo] in ${env:[foo]} - rather than being used as-is - is interpreted as a wildcard expression that matches a single character that is either f or o ([foo] is a character set or range ([...]) that matches any one of the (distinct) characters inside - see about_Wildcards).
On assigning to ${env:[foo]}, the logic of Set-Content -Path requires that a wildcard-based path resolve to something existing, even though you're generally not required to explicitly create environment variables; e.g., ${env:NoSuchVarExistsYet} = 'new' works just fine.
Workaround:
Use double(!)-`-escaping of the wildcard metacharacters:
# Namespace variable notation only works with if you
# double(!)-backtick-escape the wildcard metacharacters:
# Assign to / implicitly create env. var '[foo]'
${env:``[foo``]} = 'bar'
# Get its value.
${env:``[foo``]}
Note:
Escaping shouldn't be required at all, because there is no good reason to treat paths that conceptually identify a given, known item as wildcard expressions - see GitHub issue #9225.
That double `-escaping is needed is an added quirk - see GitHub issue #7999.
Another workaround - one that doesn't involve escaping - is to use
Set-Content -LiteralPath env:[foo] bar and Get-Content -LiteralPath env:[foo], but that is both verbose and slow.
As for the other syntax variations you tried:
$env:${[foo]}="bar"
Since your variable reference isn't {...}-enclosed as a whole (except for the initial $), the token that follows the : is only allowed to contain characters that do not require escaping - and $, { and } all violate that rule.
{...}-enclosing the entire path - ${env:[foo]} - solves the syntax problem, but runs into the problem detailed above.
Set-Item -LiteralPath env:${[foo]} -Value "bar"
This does not work in general, because string expansion is applied beforehand here - it is as if you had passed "env:${[foo]}": the reference to a (regular) variable named ${[foo]} is expanded (replaced with its value) and in effect appended to literal env:, before handing the result to Set-Item.
If such a regular variable doesn't exist, what Set-Item sees is just env: (because non-existent variables default to $null, which becomes the empty string in a string context), which causes an error due to the lack of variable name.
By contrast, the following would set an environment variable named unrelated instead:
# Create a regular variable literally named '[foo]'.
${[foo]} = 'unrelated'
# !! The following sets env:unrelated, i.e., env. var 'unrelated',
# !! due to the string expansion that is performed on the -LiteralPath
# !! argument up front.
Set-Item -LiteralPath env:${[foo]} bar
$env:unrelated # -> 'bar'
The same applies to Get-Item -LiteralPath env:${[foo]} and
Set-Item -LiteralPath env:${[foo]2} -Value "bar".

PowerShell - Add-Content- Unable to add multiple vars to a file

I'm trying to add an expression to a log file which contains Date,Time some data separated by ";". Unfortunately I get an error every time I change the position of the items in the -value brackets.
Whats seems to be wrong?
This is the code :
Add-Content -path C:\...\outlog.txt -Value($Date + ';' + $Time + ';Checked;' + $strFileName)
This is the error :
Cannot convert argument "1", with value: ";", for "op_Addition" to type "System.TimeSpan": "Cannot convert
value ";" to type "System.TimeSpan". Error: "String was not recognized as a valid TimeSpan.""
At C:\...\Untitled1.ps1:8 char:64
+ ... \outlog.txt -Value($($Date + ';' + $Time + ';'+ $str))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Try this -
Add-Content -path C:\...\outlog.txt -Value("$Date; $Time; Checked; $strFileName")
If you look at get-help Add-Content -full, and look at the -value parameter, you will see -
-Value <Object[]>
Specifies the content to be added. Type a quoted string, such as "This data is for internal use only", or
specify an object that contains content, such as the DateTime object that Get-Date generates.
You cannot specify the contents of a file by typing its path, because the path is just a string, but you can
use a Get-Content command to get the content and pass it to the Value parameter.
Required? true
Position? 1
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? false
It says that it expects a quoted string or an object that contains content. It was missing in your case and hence the + operator was trying to add $date and time.

How to extract a certain part of a string in powershell

I want to extract the last 4 digits before ".txt" from this string:
09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK
Those represent the time at which that log was created and I want to display it as 10:58. I read from a file that has multiple lines similar to the one displayed.
Get-Content file.txt | ForEach-Object {
$splitUp = $_ -split "_"
$SC=$splitUp[2] -split "_"
Write-Host $SC
$len = $SC.Length
$folder2 = $SC.Substring($len - 12, 42)
}
I tried separating the string by "_" and then counting the characters in the obtained string and tried separating by the "Substring" command, but I receive the following error.
Exception calling "Substring" with "2" argument(s): "StartIndex cannot
be less than zero. Parameter name: startIndex"
At line:6 char:5
+ $folder2 = $SC.Substring($len - 12, 42)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : ArgumentOutOfRangeException
You can use a regex "lookahead".
What you are searching for is a set of four digits followed by ".txt":
$string = "09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK"
$regex = "\d{4}(?=\.txt)"
[regex]::matches($string, $regex).value
There's probably a more elegant solution:
$String = '09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK'
$String -Match '.*(?=\.txt)' | Out-Null
$Match = $Matches[0][-4..-1] -Join ''
$Time = [DateTime]::ParseExact($Match, 'HHmm',[CultureInfo]::InvariantCulture)
$Time.ToShortTimeString()
Uses RegEx to get all of the string before the .txt
Uses the Array Index to get the characters from 4th to last to the last character and joins them together as a single string.
Casts the value as a DateTime object using ParseExact to interpret it as 24 hour time code
Outputs the Short Date value of that DateTime object.
Just do it with Substring and IndexOf:
$string="09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK"
$string.Substring($string.IndexOf('.txt')-4, 4)

How to escape characters inside of a parameter in Powershell?

This is a simplified version of my function:
function DetectLocalUser($localGroup, $members)
{
$result = net localgroup "$localGroup"
#$members= $members.Replace("\","\\")
if ($result -match $members)
{
return $true
}
else
{
return $false
}
}
To invoke the function I use this example (Typical values I am going to receive):
DETECTLocalUser "test" "iis apppool\userapi"
The parameters are not controlled by me. If they were I would escape directly the second parameter "iis apppool\\userapi"
On execution I have a problem with the \ in the parameter. The exact error is:
parsing "iis apppool\icisapi" - Unrecognized escape sequence \i. At
C:\k\a.ps1:6 char:9
+ if ($result -match $members)
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException
I found a workaround by adding #$members= $members.Replace("\","\\") fixes the problem but I am not sure if is the best option.
Is my workaroud acceptable or is there a better way of escaping $members parameter?
[RegEx]::Escape($members)
That will ensure that characters in strings get interpreted as literals and not as part of the RegEx.
To explain further, the -match operator is doing a regular expression match, so the string you pass to it is interpreted as a regular expression.
Backslash happens to be the escape character in a regular expression, so that's where your issue is. Using [RegEx]::Escape() ensures that other characters won't be interpreted, such as [,],.,+,(,),^,$,?,*, etc.

replace exception in powershell

I'm a beginner in powershell and know C# pretty well. I have this command http://www.f2ko.de/programs.php?lang=en&pid=cmd that downloads stuff. I'm writing this script to download all the sgf go games from this url http://www.gogameworld.com/gophp/pg_samplegames.php, and was trying to write a powershell script to do it for me. So I wrote a script:
Get-Content test.txt|
ForEach-Object
{
if($_ -eq "=`"javascript:viewdemogame(`'*.sgf`')`" tit")
{
$filename = $_ -replace '=`"javascript:viewdemogame(`''
$filename = $filename -replace '`')`" tit'
&"(Path)/download.exe" ("http://www.gogameworld.com/webclient/qipu/" + $filename)
}
}
However, when I run the script, I keep getting this error:
Unexpected token '`'' in expression or statement.
At (PATH)\test.ps1:7 char:37
+ $filename = $filename -replace '`' <<<< )'
+ CategoryInfo : ParserError: (`':String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
I've looked at the script lots of times and still can't figure out whats wrong. Thanks.
Try this, read the content of the file as one string and then use the Regex.Matches to get all occurrences of the text contained in the parenthesis:
$content = Get-Content test.txt | Out-String
$baseUrl = 'http://www.gogameworld.com/webclient/qipu/'
[regex]::matches($content,"javascript:viewdemogame\('([^\']+)'\)") | Foreach-Object{
$url = '{0}{1}' -f $baseUrl,$_.Groups[1].Value
& "(Path)/download.exe" $url
}
here's an explanation of the regex pattern (created with RegexBuddy):
javascript:viewdemogame\('([^\']+)'\)
Match the characters “javascript:viewdemogame” literally «javascript:viewdemogame»
Match the character “(” literally «\(»
Match the character “'” literally «'»
Match the regular expression below and capture its match into backreference number 1 «([^\']+)»
Match any character that is NOT a ' character «[^\']+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Match the character “'” literally «'»
Match the character “)” literally «\)»
Match the character “"” literally «"»
'{0}{1}' is used with the -f operator to create a string. {0} maps to the first value on the right hand side of the operator (e.g $baseUrl) and {1} is mapped to the second value. Under the hood, PowerShell is suing the .NET String.Format method. You can read more about it here: http://devcentral.f5.com/weblogs/Joe/archive/2008/12/19/powershell-abcs---f-is-for-format-operator.aspx
'')" tit'
The -replace operator takes 2 arguments, comma separated. The first is a regular expression that matches what you want replaced. The second is the string you want to relace that with. You appear to be missing the second argument.