Powershell Command for retrieving the second pattern values - powershell

I am facing problem while using multiple patterns to retrieve the values from the second pattern.
The file contains data like below
Explore/CommonServices/AlertService.Folder
Explore/CommonServices/CIHLogger.Folder
What I am trying to do is find the text between two forward slashes i.e CommonServices and find the text between one forward slash and the dot i.e AlertService
I am able to find them using the patterns '/(.+)/' and '/([^/]+)\.' respectively. Now the challenge is how to get them into a single line
My Command is
((get-content "test2.txt") | Select-String -pattern '/(.+)/','/([^/]+)\.' -context 0,2 | foreach {"iics export --podHostName dm-us.informaticacloud
.com -r us -u xxxxxx -p xxxxxxxxx --artifacts " + $_ + " --zipFilePath `"C:\Users\breddy002\Documents\NJR\SVN\" + $_.Matches[0].Groups[1].Value + "\" + $($_.Matches[1].Groups[1].value)
})
I am not sure how to get the second pattern output in the second output
Powershell version is : echo $PSVersionTable
Name Value
---- -----
PSVersion 5.1.17763.771

You could do something like the following:
switch -regex -file 'text2.txt' {
'/(?<Slash>[^/]+)/(?<Dot>[^/\.]+)\.' {
$Slash = $Matches.Slash
$Dot = $Matches.Dot
"First: {0}, Second: {1}" -f $Slash,$Dot
}
}
Explanation:
The switch statement is a robust if statement. With the -regex and -file parameters, you can efficiently read in each line of a file and apply regex pattern matches. Each successful match is stored in the automatic variable $Matches.
The regex pattern /(?<Slash>[^/]+)/(?<Dot>[^/\.]+)\. matches as follows:
/ is a literal match of /
(?<Slash>[^/]+) matches one or more (+) characters that are not / ([^/]). That match is stored as capture group Slash (using syntax (?<Slash>)). It can later be accessed by using the syntax $Matches.Slash.
(?<Dot>[^/\.]+) matches one or more characters that are not / and . ([^/\.]+). That match is stored as capture group Dot. It can later be accessed by using the syntax $Matches.Dot.
\. is a literal . match, which requires escaping with backslash.

Related

Parse info from Text File - Powershell

Beginner here, I am working on a error log file and library, the current step I am on is to pull specific information from a txt file.
The code I have currently is...
$StatusErr = "Type 1","Type 2"
for ($i=0; $i -lt $StatusErr.length; $i++) {
get-content C:\blah\Logs\StatusErrors.TXT |
select-string $StatusErr[$i] |
add-content C:\blah\Logs\StatusErrorsresult.txt
}
while it is working, I need it to display as
Type-1-Description
2-Description
Type-1-Description
2-Description
Type-1-Description
2-Description
etc.
it is currently displaying as
Type 1 = Type-1-Description
Type 1 = Type-1-Description
Type 1 = Type-1-Description
Type 2 = 2-Description
Type 2 = 2-Description
Type 2 = 2-Description
I am unsure how to change the arrangement and remove unneeded spaces and the = sign
You need to search for both patterns in a single Select-String call in order to get matching lines in order.
While the -Pattern parameter does accept an array of patterns, in this case a single regex will do.
You need to use a regex pattern in order to capture and output only part of the lines that match.
$StatusErrRegex = '(?<=Type [12]\s*=\s*)[^ ]+'
get-content C:\blah\Logs\StatusErrors.TXT |
select-string $StatusErrRegex |
foreach-object { $_.Matches.Value } |
set-content C:\blah\Logs\StatusErrorsresult.txt
Note that I've replaced add-content with set-content, as I'm assuming you don't want to append to a preexisting file. set-content writes all objects it receives via the pipeline to the output file.
Select-String outputs Microsoft.PowerShell.Commands.MatchInfo instances whose .Matches property provides access to the part of the line that was matched.
For an explanation of the regex and the ability to experiment with it, see this regex101.com page.
Additional notes:
Select-String, like PowerShell in general, is case-insensitive by default; add the -CaseSensitive switch, if needed.
(?<=...) is a (positive) lookbehind assertion, whose matching text doesn't became part of what the regex captures.
\s* matches zero or more whitespace characters; \s+ would match one or more.
[^ ]+ matches one or more (+) characters that are not ^ spaces ( ), and thereby captures the run of non-space characters to the right of the = sign.
To match any of multiple words at the start of the pattern, use a regex alternation (|), e.g. '(?<=(type|data) [12]\s*=\s*)[^ ]+'

add quotation mark to a text file powershell

I need to add the quotation mark to a text file that contains 500 lines text.
The format is inconsistent. It has dashes, dots, numbers, and letters. For example
1527c705-839a-4832-9118-54d4Bd6a0c89
16575getfireshot.com.FireShotCaptureWebpageScreens
3EA2211E.GestetnerDriverUtility
I have tried to code this
$Flist = Get-Content "$home\$user\appfiles\out.txt"
$Flist | %{$_ -replace '^(.*?)', '"'}
I got the result which only added to the beginning of a line.
"Microsoft.WinJS.2.0
The expected result should be
"Microsoft.WinJS.2.0"
How to add quotation-mark to the end of each line as well?
There is no strict need to use a regex (regular expression) in your case (requires PSv4+):
(Get-Content $home\$user\appfiles\out.txt).ForEach({ '"{0}"' -f $_ })
Array method .ForEach() processes each input line via the script block ({ ... }) passed to it.
'"{0}"' -f $_ effectively encloses each input line ($_) in double quotes, via -f, the string-format operator.
If you did want to use a regex:
(Get-Content $home\$user\appfiles\out.txt) -replace '^|$', '"'
Regex ^|$ matches both the start (^) and the end ($) of the input string and replaces both with a " char., effectively enclosing the input string in double quotes.
As for what you tried:
^(.*?)
just matches the very start of the string (^), and nothing else, given that .*? - due to using the non-greedy duplication symbol ? - matches nothing else.
Therefore, replacing what matched with " only placed a " at the start of the input string, not also at the end.
You can use regex to match both:
The beginning of the line ^(.*?)
OR |
The End of the line $
I.e. ^(.*?)|$
$Flist = Get-Content "$home\$user\appfiles\out.txt"
$Flist | %{$_ -replace '^(.*?)|$', '"'}

How to compare two sequential strings in a file

I have a big file consists of "before" and "after" cases for every item as follows:
case1 (BEF) ACT
(AFT) BLK
case2 (BEF) ACT
(AFT) ACT
case3 (BEF) ACT
(AFT) CLC
...
I need to select all of the strings which have (BEF) ACT on the "first" string and (AFT) BLK on the "second" and place the result to a file.
The idea is to create a clause like
IF (stringX.LineNumber consists of "(BEF) ACT" AND stringX+1.LineNumber consists of (AFT) BLK)
{OutFile $stringX+$stringX+1}
Sorry for the syntax, I've just starting to work with PS :)
$logfile = 'c:\temp\file.txt'
$matchphrase = '\(BEF\) ACT'
$linenum=Get-Content $logfile | Select-String $matchphrase | ForEach-Object {$_.LineNumber+1}
$linenum
#I've worked out how to get a line number after the line with first required phrase
Create a new file with a result as follows:
string with "(BEF) ACT" following with a string with "(AFT) BLK"
Select-String -SimpleMatch -CaseSensitive '(BEF) ACT' c:\temp\file.txt -Context 0,1 |
ForEach-Object {
$lineAfter = $_.Context.PostContext[0]
if ($lineAfter.Contains('(AFT) BLK')) {
$_.Line, $lineAfter # output
}
} # | Set-Content ...
-SimpleMatch performs string-literal substring matching, which means you can pass the search string as-is, without needing to escape it.
However, if you needed to further constrain the search, such as to ensure that it only occurs at the end of a line ($), you would indeed need a regular expression with the (implied) -Pattern parameter: '\(BEF\) ACT$'
Also note PowerShell is generally case-insensitive by default, which is why switch -CaseSensitive is used.
Note how Select-String can accept file paths directly - no need for a preceding Get-Content call.
-Context 0,1 captures 0 lines before and 1 line after each match, and includes them in the [Microsoft.PowerShell.Commands.MatchInfo] instances that Select-String outputs.
Inside the ForEach-Object script block, $_.Context.PostContext[0] retrieves the line after the match and .Contains() performs a literal substring search in it.
Note that .Contains() is a method of the .NET System.String type, and such methods - unlike PowerShell - are case-sensitive by default, but you can use an optional parameter to change that.
If the substring is found on the subsequent line, both the line at hand and the subsequent one are output.
The above looks for all matching pairs in the input file; if you only wanted to find the first pair, append | Select-Object -First 2 to the Select-String call.
Another way of doing this is to read the $logFile in as a single string and use a RegEx match to get the parts you want:
$logFile = 'c:\temp\file.txt'
$outFile = 'c:\temp\file2.txt'
# read the content of the logfile as a single string
$content = Get-Content -Path $logFile -Raw
$regex = [regex] '(case\d+\s+\(BEF\)\s+ACT\s+\(AFT\)\s+BLK)'
$match = $regex.Match($content)
($output = while ($match.Success) {
$match.Value
$match = $match.NextMatch()
}) | Set-Content -Path $outFile -Force
When used the result is:
case1 (BEF) ACT
(AFT) BLK
case7 (BEF) ACT
(AFT) BLK
Regex details:
( Match the regular expression below and capture its match into backreference number 1
case Match the characters “case” literally
\d Match a single digit 0..9
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
\s Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
\( Match the character “(” literally
BEF Match the characters “BEF” literally
\) Match the character “)” literally
\s Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
ACT Match the characters “ACT” literally
\s Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
\( Match the character “(” literally
AFT Match the characters “AFT” literally
\) Match the character “)” literally
\s Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
BLK Match the characters “BLK” literally
)
My other answer completes your own Select-String-based solution attempt. Select-String is versatile, but slow, though it is appropriate for processing files too large to fit into memory as a whole, given that it processes files line by line.
However, PowerShell offers a much faster line-by-line processing alternative: switch -File - see the solution below.
Theo's helpful answer, which reads the entire file into memory first, will probably perform best overall, depending on file size, but it comes at the cost of increased complexity, due to relying heavily on direct use of .NET functionality.
$(
$firstLine = ''
switch -CaseSensitive -Regex -File t.txt {
'\(BEF\) ACT' { $firstLine = $_; continue }
'\(AFT\) BLK' {
# Pair found, output it.
# If you don't want to look for further pairs,
# append `; break` inside the block.
if ($firstLine) { $firstLine, $_ }
# Look for further pairs.
$firstLine = ''; continue
}
default { $firstLine = '' }
}
) # | Set-Content ...
Note: The enclosing $(...) is only needed if you want to send the output directly to the pipeline to a cmdlet such as Set-Content; it is not needed for capturing the output in a variable: $pair = switch ...
-Regex interprets the branch conditionals as regular expressions.
$_ inside a branch's action script block ({ ... } refers to the line at hand.
The overall approach is:
$firstLine stores the 1st line of interest once found, and when the 2nd line's pattern is found and $firstLine is set (is nonempty), the pair is output.
The default handler resets $firstLine, to ensure that only two consecutive lines that contain the strings of interest are considered.

Get part of a string from the output of Get-Item in Powershell

My powershell command below
$BUILD_SOURCEVERSIONMESSAGE= (Get-Item Env:\BUILD_SOURCEVERSIONMESSAGE)
returns output in this format
2018-10-26T01:08:44.7409834Z BUILD_SOURCEVERSIONMESSAGE Merge 569594f057e2c4bd0320159855e81e14216ca66f into 41107d0f0db5ef2986831db2182280e0c...
I am trying to parse the string 569594f057e2c4bd0320159855e81e14216ca66f from the output above.
I tried converting the output to a string, splitting it on whitespace, and accessing the second element of the array as follows. However, I get empty string. How can I access the required string?
echo $BUILD_SOURCEVERSIONMESSAGE
$out = $BUILD_SOURCEVERSIONMESSAGE | Out-String
$out1 = $out.split()
echo $out1[1]
The concise equivalent of command Get-Item Env:\BUILD_SOURCEVERSIONMESSAGE - i.e., retrieving the value of environment variable BUILD_SOURCEVERSIONMESSAGE - is the expression $env:BUILD_SOURCEVERSIONMESSAGE.
Using the unary form of Powershell's -split operator, which splits the input by any nonempty run of whitespace (while stripping leading and trailing whitespace), you can get the desired output as follows:
PS> (-split $env:BUILD_SOURCEVERSIONMESSAGE)[3]
569594f057e2c4bd0320159855e81e14216ca66f
Index 3 extracts the 4th token resulting from the tokenization via -split.
If you want to use string interpolation with the result:
$prefix = 'before<'; $postfix = '>after'
$val = (-split $env:BUILD_SOURCEVERSIONMESSAGE)[3]
# Output a synthesized string that applies a pre- and postfix, using
# {...} to enclose variable names to avoid ambiguity.
"${prefix}${val}${postfix}"
The above yields:
before<569594f057e2c4bd0320159855e81e14216ca66f>after

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.