Return first matching line - powershell

I have an XML command that returns a list of URLs, example
PS > $xml.rss.channel.item.link
http://example.com/20140704.exe
http://example.com/20140704.tar.xz
http://example.com/20140624.exe
http://example.com/20140624.tar.xz
http://example.com/20140507.tar.xz
From this list, I would like to return the first .tar.xz line. I have this
command
$xml.rss.channel.item.link | ? {$_ -match '.tar.xz'} | select -first 1
But I would prefer a command with only one pipe if possible.

You don't need a pipe at all:
(Select-Xml -Xml $xml -XPath "(//link[contains(.,'.tar.xz')])[1]").Node.InnerText
Note: XPath is case-sensitive. If that is an issue, you can use a trick with translate() function and force it to ignore the case.

A different way using two pipes
$xml.rss.channel.item.link | Select-String .tar.xz | select -first 1
One pipe
($xml.rss.channel.item.link | Select-String .tar.xz)[0]

Related

ForEach-Object OutString, Powershell Awk Equivalents

I'm a long time Bash enthusiast trying to get my bearings with Powershell. I'm trying to do something that could easily be accomplished with Awk, but I can't seem to find a solution in Powershell documentation. I'm essentially trying to select the third value from the output of the command delimited by /
Get-ADOrganizationalUnit -Properties CanonicalName -Filter * | Select-Object -ExpandProperty CanonicalName | Select-String ".*/Example/.*"
example.local/Example/ExampleOU1
example.local/Example/ExampleOU2
I just want to select the last value shown here. In Bash land this could easily be accomplished by an awk -F "/" '{print $3}' however I'm struggling to find the equivalent in Powershell. I found Out-String | %{ $_.Split('/')[2]; }' which is nice, but only works if there's one object. I'm assuming I need to ForEach-Object, then convert to a string, then split, but I'm not sure how.
I almost never use out-string. Canonicalname is a property of the object, so you need to reference that property. This would work:
[pscustomobject]#{canonicalname = 'example.local/Example/ExampleOU1'} |
% { $_.canonicalname.Split('/')[2] }
ExampleOU1
There's also -split which uses regex:
[pscustomobject]#{canonicalname = 'example.local/Example/ExampleOU1'} |
% { ($_.canonicalname -split '/')[2] }
Paths come up so often there's a command for it:
[pscustomobject]#{canonicalname = 'example.local/Example/ExampleOU1'} |
% { split-path -leaf $_.canonicalname }

Powershell `echo -e "1\n2\n3" | tail -n1` equivalent

There are countless examples about how to get tail for file content, but there is no for pipes.
Is there any way to get last line from pipe ?
I have long chain of piped commands and I want last 1 line only.
If you want the last object, that is send through the pipe, Select-Object can do that for you:
$input | Select-Object -Last 1
If you are only interested in one particular property of this object, you can expand this property in the same statement:
[pscustomobject]#{propname = 'foo'},[pscustomobject]#{propname = 'bar'} |
Select-Object -Last 1 -ExpandProperty propname
Or -1 is the last element of an array.
(echo 1 2 3)[-1]
3

Formatting variable with 2 outputs

Code:
$adgroups = Get-ADPrincipalGroupMembership $tag$ | select -ExpandProperty Name | Sort | Select-String "iSite"
Output:
DFSR Managed iSite Enterprise 4.4.542.2 WSA_Rad_A
DFSR Managed iSite Radiology 4.4.516.27 WSA_Rad_A
Basically one command generates two items (output using $variable | out-file C:\file.txt -Append) and when I go to open these in excel they format as one line like this:
DFSR Managed iSite Enterprise 4.4.542.2 WSA_Rad_A DFSR Managed iSite Radiology 4.4.516.27 WSA_Rad_A
Is there a way to break it up // add a new line after each item but still keep them both inside one variable?
Get-ADPrincipalGroupMembership $tag$ | select -ExpandProperty Name | Sort | Select-String "iSite" | ConvertTo-Csv -NoTypeInformation | Out-File C~\Desktop\Sites.csv
I would break up your request a bit.
First, you're using Select -Expand, which is going to discard all of the properties and only return the values for each object's Name. This is a problem because when you export it as a CSV, you're not going to have a heading. I think the lack of header is ultimately leading to the issue you're facing here.
Try this instead:
$adgroups = Get-ADPrincipalGroupMembership $tag$ | Where Name -like "*iSite*" |
select Name | Export-Csv c:\pathto\YourCsv.Csv
Finally, I don't think Select-String is doing you any favors. You could instead use the -like operator.

using powershell pipes to output property of matchitem object

I'm trying to use a powershell pipe to do the following which doesn't work. Has anyone got a suggestion on how I can do this in one step
$a = bcdedit /enum | select-string "identifier.*current" | $-.line
at the moment I'm needing to do the following
$aobj = bcdedit /enum | select-string "identifier.*current"
$a = $aobj.line
Is there a way I can combine this into one line?
The following should work provided you are pulling a single line from the BCDEDIT output:
$a = (bcdedit /enum | select-string "identifier.*current").line
If you might get multiple lines, the following will return an array of lines:
$a = bcdedit /enum | select-string "identifier.*current" | foreach-object { $_.Line }
Take you pick :)
If you want to get a property of an object by itself, the usual way to do it is with Select-Object -ExpandProperty.
bcdedit /enum | select-string "identifier.*current" | Select-Object -ExpandProperty Line

analog command grep -o in Powershell

What command in Powershell replaces grep -o (which displays only the matched portion of a line instead of a whole line) ?
i try use Select-Object but it always display full line.
For example:
next line
<a id="tm_param1_text1_item_1" class="tm_param1param2_param3 xxx_zzz qqq_rrrr_www_vv_no_empty" >eeee <span id="ttt_xxx_zzz">0</span></a>
use next command:
cat filename | grep -o '>[0-9]' | grep -o '[0-9]'
output: 0
When i use Select-Object i always see full line (
One way is:
$a = '<a id="tm_param1_text1_item_1" class="tm_param1param2_param3 xxx_zzz qqq_rrrr_www_vv_no_empty" >eeee <span id="ttt_xxx_zzz">0</span></a>'
$a -match '>([0-9])<' #returns true and populate the $matches automatic variable
$matches[1] #returns 0
For selecting strings in text, use select-string rather than select-object. It will return a MatchInfo object. You can access the matches by querying the matches property:
$a = '<a id="tm_param1_text1_item_1" class="tm_param1param2_param3 xxx_zzz qqq_rrrr_www_vv_no_empty" >eeee <span id="ttt_xxx_zzz">0</span></a>'
($a | select-string '>[0-9]').matches[0].value # returns >0
InPowerShell v3:
sls .\filename -pattern '^[0-9]' -AllMatches | % matches | % value
Explanation:
sls is an alias for Select-String. It takes a filename/path as well as a pattern as parameters. It produces "matches"
% matches selects all matches regardless of file etc.
% value selects the value of each match
The solutions that have been proposed so far only produce the first match from each line. To fully emulate the behavior of grep -o (which produces every match from each line) something like this is required:
Get-Content filename | Select-String '>([0-9])' -AllMatches |
Select-Object -Expand Matches | % { $_.Groups[1].Value }
Select-String -AllMatches returns all matches from an input string.
Select-Object -Expand Matches "disconnects" matches from the same line, so that all submatches can be selected via $_.Groups[1]. Without this expansion the submatch from the second match of a line would be $_.Groups[3].