There is a Linux script which is taking docker volume and displaying volumes matches string.
docker volume ls | grep -i $volname | awk '{print $2}'
I need to convert this script to work in windows environment. So PowerShell is my choice. Select-String works more or less like grep.
docker volume ls | Select-String $volname
but there is no equivalent to awk in PowerShell. So I tried to split using whitespace:
$volList = docker volume ls |
Select-String "winvolume" |
foreach { $_ -split " " }
but it has many empty elements (13 empty elements) in the array. I need to remove all the empty elements and have only elements with text. How to achieve this in PowerShell?
Select-String produces MatchInfo objects, from which you need to expand the relevant information first. Use PowerShell operators instead.
((docker volume ls) -match $volname -split ' +')[1]
Splitting at the expression ' +' treats consecutive spaces as a single delimiter, like awk does.
One option is to use the -split operator in a slightly different way. For example, for this string:
"this string has lots of spaces in it "
You can get only the 'words' by doing this:
-split "this string has lots of spaces in it "
Which gives:
this
string
has
lots
of
spaces
in
it
So in your case, your code would be:
$volList = docker volume ls |
Select-String "winvolume" |
foreach { -split $_ }
Another way is to use ConvertFrom-String.
docker volume ls | Select-String winvolume | ConvertFrom-String | ForEach-Object P2
It has an alias:
docker volume ls | sls winvolume | cfs | % P2
Please be aware that if the text contains decimals, they will be rounded. So it is better not to use in scripts
Related
I can manually open up PowerShell and run
wsl
ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1
To get the IP address of the Ubuntu instance. But when I try to write a script for this (100 different ways) I always get some kind of error. This is an example
$command = "ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1"
$ip = Invoke-Expression "wsl $command"
Which gives an error about grep.
Call wsl.exe via the -e option and specify bash as the executable, which allows you to use the latter's -c option with a command line specified as a single string:
# Note the need to escape $ as `$
# to prevent PowerShell from interpolating it up front inside "..."
$command = "ip addr show eth0 | grep 'inet\b' | awk '{print `$2}' | cut -d/ -f1"
wsl -e bash -c $command
A note re the choice of string literals on the PowerShell side:
Using "..." quoting rather than '...' quoting is convenient if the text contains ' characters, because it obviates the need for escaping - ditto for the inverse scenario: using '...' quoting for text that contains " chars.
However, as in POSIX-compatible shells such as Bash, the choice of the enclosing quoting characters matters in PowerShell, because the resulting behavior differs:
'...' is a verbatim (single-quoted) string.
Unlike in POSIX-compatible shells, where escaping embedded ' chars. must be emulated with '\'', PowerShell does support direct escaping, namely with ''
"..." is an expandable (double-quoted) string, i.e. subject to string interpolation for substrings that start with $
Unlike in POSIX-compatible shells, where embedded $ chars. to be used verbatim (literally) require escaping as \$, in PowerShell you must use `$, using `, the so-called backtick, PowerShell's escape character.
Or let's assume you have powershell installed in linux (there's no Get-NetIPConfiguration?).
$command = "ip addr show eth0 | select-string inet\b | % { (-split `$_)[1] } |
% { (`$_ -split '/')[0] }"
wsl -e pwsh -c $command
10.0.0.107
Or even without it, piping to windows powershell cmdlets.
wsl -e ip addr show eth0 | select-string inet\b | % { (-split $_)[1] } |
% { ($_ -split '/')[0] }
10.0.0.107
$command has to be an array of words:
$command = 'ip address show eth0'
wsl -e (-split $command) | select-string inet\b | % { (-split $_)[1] } |
% { ($_ -split '/')[0] }
I want to output text from a text file in Windows script like you can in Linux with grep:
grep -ve ^# -ve '^;' -ve ^$ /name of file.
I haven't had much success finding a solution. I am trying to use Powershell with little experience using it.
Use Select-String in place of grep:
Select-String -Path 'path/to/file' -Pattern '^[#;]|^$' -NotMatch
Select-String will output a Match object, if you just want to matched strings, grab the Line property:
Select-String ... |Select -Expand Line
Starting with PowerShell 7.0 you can also use the -Raw switch to have Select-String return only the matched strings and nothing else:
Select-String ... -Raw
This comes close. You can have an array of patterns seperated by commas. Just like in bash, the semicolon has to be quoted, because it means "end of statement" in powershell. The command avoids lines that start with "#", ";", or are blank.
'# comment',
'; semicolon',
'',
'one',
'two',
'three' | select-string ^#, '^;', ^$ -notmatch
one
two
three
This is what I used to output I was after; get-childitem zabbix_agentd.conf | select-string -pattern '^[#;]|^$' -notmatch
This is what I was after without all the lines that are commented out and spaces.
zabbix_agentd.conf:24:LogFile=C:\Program Files\Zabbix Agent\zabbix_agentd.log
zabbix_agentd.conf:88:Server=10.0.0.22
zabbix_agentd.conf:130:ServerActive=10.0.0.22
zabbix_agentd.conf:141:Hostname=RED-DOUG
zabbix_agentd.conf:257:Include=C:\Program Files\Zabbix Agent\zabbix_agentd.conf.d\
Thank you for the help, Doug
txt which have lines of logs and I only want those lines which contains the specific IP address and saves those to a new text file.
You can use to find any IP address.
Get-Content file.txt | Where {$_ -match '(\d+\.){3}\d+'} | Set-Content newfile.txt
Get-Content without the -Raw switch reads a file into an in-memory array object. | Where processes against each line for a value that matches one or more digits (\d+) followed by a . (\.). The digits plus . combination needs to be found three consecutive times ({3}) followed by one or more digits.
For a specific IP address, you can do the following:
$IPAddress = '192.98.12.5'
Get-Content file.txt | Where { $_.Contains($IPAddress) } | Set-Content newfile.txt
I am newbie on powershell. Today I tried something very simple
Alias | sls -Pattern 'echo'
which produced echo, but what I want is Alias echo -> Write-Out.
In bash, you can just do
alias | grep 'echo'
My question is why sls does not work. BTW, if I replace sls with findstr, it worked.
If you want to get an alias with a particular name you can do:
alias -name echo
The echo -> Write-Out is the DisplayName:
(alias -name echo).DisplayName
The Get-Alias command returns a sequence of objects, each of which represents a single command alias. When displayed in powershell, these objects are formatted as a table containing the CommandType, Name and ModuleName properties.
When you pipe into findstr, it is the string representations of these columns which are being filtered, so any match displays the whole table row:
Alias echo -> Write-Output
When you pipe into Select-String each object is being bound to the -InputObject parameter of the Select-String cmdlet. Since Select-String operates on text, it just calls ToString on the received object to get its string representation.
ToString only returns the Name property. You can see this by executing the following:
alias | %{$_.tostring()}
Therefore any matches from Select-String only match on the alias name.
select-string only behaves like grep when used with a text file. With a powershell object, the behavior changes (as Lee explained in his answer).
This can be demonstrated with:
alias > out.txt; cat out.txt | sls -pattern 'echo'
Which returns Alias echo -> Write-Output because now slsis operating on a text file.
The other solutions to do what you want are:
alias | where DisplayName -like '*echo*'
alias | out-string -stream | sls -pattern 'echo'
This converts the powershell object to a string so that sls works like grep.
I have lots of text output from a tool that I want to parse in Powershell 2.0. The output is nicely formatted so I can construct a regex to pull out the data I want using select-string. However getting the subsequent matches out of select-string seems long-winded. There has to be a shorter way?
This works:
p4 users | select-string "^\w+(.\w+)?" |
select -Expand Matches | %{p4 changes -u $_.Value}
But All those Matches and Values are verbose. There's nothing obvious in the select-string help file, but is there a way to make it pump out just the regex matches as strings? A bit like:
p4 users | select-string "^\w(.\w+)?" -ImaginaryMagicOption | %{p4 changes -u $_}
In this case, it may be a bit easier to use -match e.g.:
p4 users | Foreach {if ($_ -match '^\w+(.\w+)?') { p4 changes -u $matches[0] }}
This is only because the output of Select-String is MatchInfo object that buries the Matches info one level down. OTOH it can be made to work:
p4 users | Select-String "^\w+(.\w+)?" |
Foreach {p4 changes -u $_.Matches[0].Value}