I run a cmdlet in powershell which returns a string eg;
123##EXT#outlook.com
456#outlook.com
789#outlook.com
I'm looking for a way to remove the #EXT# characters from the string. I can do everything but remove this and am struggling to find any documentation :/
Lets assume the cmdlet outputs an array of strings. This is simulated by the $adr variable.
#Array of strings
$adr = #(
"123##EXT#outlook.com"
"456#outlook.com"
"789#outlook.com"
)
$adr|foreach {$_ -replace "#EXT#",""}
Related
I've seen the # symbol used in PowerShell to initialise arrays.
What exactly does the # symbol denote and where can I read more about it?
In PowerShell V2, # is also the Splat operator.
PS> # First use it to create a hashtable of parameters:
PS> $params = #{path = "c:\temp"; Recurse= $true}
PS> # Then use it to SPLAT the parameters - which is to say to expand a hash table
PS> # into a set of command line parameters.
PS> dir #params
PS> # That was the equivalent of:
PS> dir -Path c:\temp -Recurse:$true
PowerShell will actually treat any comma-separated list as an array:
"server1","server2"
So the # is optional in those cases. However, for associative arrays, the # is required:
#{"Key"="Value";"Key2"="Value2"}
Officially, # is the "array operator." You can read more about it in the documentation that installed along with PowerShell, or in a book like "Windows PowerShell: TFM," which I co-authored.
While the above responses provide most of the answer it is useful--even this late to the question--to provide the full answer, to wit:
Array sub-expression (see about_arrays)
Forces the value to be an array, even if a singleton or a null, e.g. $a = #(ps | where name -like 'foo')
Hash initializer (see about_hash_tables)
Initializes a hash table with key-value pairs, e.g.
$HashArguments = #{ Path = "test.txt"; Destination = "test2.txt"; WhatIf = $true }
Splatting (see about_splatting)
Let's you invoke a cmdlet with parameters from an array or a hash-table rather than the more customary individually enumerated parameters, e.g. using the hash table just above, Copy-Item #HashArguments
Here strings (see about_quoting_rules)
Let's you create strings with easily embedded quotes, typically used for multi-line strings, e.g.:
$data = #"
line one
line two
something "quoted" here
"#
Because this type of question (what does 'x' notation mean in PowerShell?) is so common here on StackOverflow as well as in many reader comments, I put together a lexicon of PowerShell punctuation, just published on Simple-Talk.com. Read all about # as well as % and # and $_ and ? and more at The Complete Guide to PowerShell Punctuation. Attached to the article is this wallchart that gives you everything on a single sheet:
You can also wrap the output of a cmdlet (or pipeline) in #() to ensure that what you get back is an array rather than a single item.
For instance, dir usually returns a list, but depending on the options, it might return a single object. If you are planning on iterating through the results with a foreach-object, you need to make sure you get a list back. Here's a contrived example:
$results = #( dir c:\autoexec.bat)
One more thing... an empty array (like to initialize a variable) is denoted #().
The Splatting Operator
To create an array, we create a variable and assign the array. Arrays are noted by the "#" symbol. Let's take the discussion above and use an array to connect to multiple remote computers:
$strComputers = #("Server1", "Server2", "Server3")<enter>
They are used for arrays and hashes.
PowerShell Tutorial 7: Accumulate, Recall, and Modify Data
Array Literals In PowerShell
I hope this helps to understand it a bit better.
You can store "values" within a key and return that value to do something.
In this case I have just provided #{a="";b="";c="";} and if not in the options i.e "keys" (a, b or c) then don't return a value
$array = #{
a = "test1";
b = "test2";
c = "test3"
}
foreach($elem in $array.GetEnumerator()){
if ($elem.key -eq "a"){
$key = $elem.key
$value = $elem.value
}
elseif ($elem.key -eq "b"){
$key = $elem.key
$value = $elem.value
}
elseif ($elem.key -eq "c"){
$key = $elem.key
$value = $elem.value
}
else{
Write-Host "No other value"
}
Write-Host "Key: " $key "Value: " $value
}
I have a PSObject which contains the following Values
AZREUS/MYVM-0.mydomain.com
AZREUS/MYVM-1.mydomain.com
I need only the VM name stored in a new PS-Object, how can I do that.
The list should return like below.
MYVM-0
MYVM-1
a simple way can be to use -replace operator:
$list = #('AZREUS/MYVM-0.mydomain.com','AZREUS/MYVM-1.mydomain.com')
$list -replace 'AZREUS/'-replace '\.mydomain\.com'
YannCha's answer is an efficient answer if your strings always begin with AZREUS/ and end with .mydomain.com. You can use a single -replace to get the desired result.
$obj = 'AZREUS/MYVM-0.mydomain.com','AZREUS/MYVM-1.mydomain.com'
$obj -replace '^AZREUS/(.*)\.mydomain\.com$','$1'
$1 represents capture group 1, which was created by the first parentheses grouping (). It contains .* contents. See Regex for regex explanation.
Taking the same approach further dynamically, you can use pattern matching. This removes all beginning characters including the first /. Then removes the first . and all characters after it.
$obj -replace '^.*/(.*?)\..*$','$1'
See Regex for regex explanation.
Note that if your object items are not strings, they will need to support being converted to strings or you will have to do that yourself before applying -replace.
Or using -match. Do them one at a time.
'AZREUS/MYVM-0.mydomain.com' -match 'AZREUS/(.*).mydomain.com' > $null; $matches[1]
MYVM-0
'AZREUS/MYVM-1.mydomain.com' -match 'AZREUS/(.*).mydomain.com' > $null; $matches[1]
MYVM-1
Below is the code where I am taking server names from a text file and concatenating with comma.
But when I am printing the value, it is coming with an extra new line after the values.
I tried doing $erversToReboot.Trim(), but didn't helped.
$ServerList = Get-Content "D:\ServerName.txt"
$Servers=""
foreach($Server in $ServerList)
{
$Servers += $Server + ","
}
[string]$ServersToReboot= $Servers.TrimEnd(",")
The output coming as
server1,server2
---one extra line here---
Please let me know what is going wrong here.
Best as I can tell, you're attempting to comma separate your servers. I'd skip the Foreach construct myself and simply use the join operator.
$ServerList = Get-Content -Path 'D:\ServerName.txt'
$ServerList -join ','
This can be done in a single statement, as well.
$ServerList = (Get-Content -Path 'D:\ServerName.txt') -join ','
Tommy
As others have noted, it's in general much simpler to use the -join operator to join the input lines with a specifiable separator.
As for the problem of an extra empty line: Gert Jan Kraaijeveld plausibly suggests that your input file has an extra empty line at the end, while noting that it is actually not what would happen with the code you've posted, which should work fine (despite its inefficiency).
Perhaps the extra line is an artifact of how you're printing the resulting value.
To answer the related question of how to ignore empty lines in the input file:
Assuming that it is OK to simply remove all empty lines from the input, the simplest PowerShell-idiomatic solution is:
#(Get-Content D:\ServerName.txt) -ne '' -join ','
#(Get-Content D:\ServerName.txt) returns the input lines as an array[1] of strings, from which -ne '' then removes empty lines, and the result of which -join joins with separator ,
[1] Get-Content D:\ServerName.txt would return a scalar (single string), if the input file happened to contain only 1 line, because PowerShell generally reports a single output object as itself rather than as a single-element array when pipeline output is collected.
Because of that, #(...), the array-subexpression operator - instead of just (...) - is needed in the above command: it ensures that the output from Get-Command is treated as an array, because the -ne operator acts differently with a scalar LHS and returns a Boolean rather than filtering the LHS's elements: compare 'foo' -ne '' to #('foo') -ne ''.
By contrast, the #(...) is not necessary if you pass the result (directly) to -join (which simply is a no-op with a scalar LHS):
(Get-Content D:\ServerName.txt) -join ','
It certainly seemed like a simple enough task but for whatever reason this doesn't work:
#Verifies that the firefox proxy setting have been applied
#locate Prefsjs file
$PrefsFiles = Get-Item -Path ($env:SystemDrive+"\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\*\prefs.js")
#read in Prefsjs
$Prefsjs = (Get-Content $PrefsFiles)
#Block to compare
$Update= #"
user_pref("network.proxy.http", "0.0.0.0");
user_pref("network.proxy.http_port", 80);
"#
($Prefsjs -contains $Update)
The last line should return a true because the text actually does exist in $Prefsjs... Any ideas?
It's not going to match because you're comparing a multi-line string to an array of single line strings.
You need to compare like objects, which means $Prefsjs also needs to be a single, multi-line string. The easiest way to do that is to add the -Raw switch to your Get-Content:
#read in Prefsjs
$Prefsjs = (Get-Content $PrefsFiles -Raw)
But now $Prefsjs is not an array any more, so you can't use -Contains. It's now just a single string, so you can use the string contains() method to accomplish the same thing:
$Prefsjs.contains($Update)
I have a string in the form -content-, and I would like to replace it with &content&. How can I do this with replace in PowerShell?
PowerShell strings are just .NET strings, so you can:
PS> $x = '-foo-'
PS> $x.Replace('-', '&')
&foo&
...or:
PS> $x = '-foo-'
PS> $x.Replace('-foo-', '&bar&')
&bar&
Obviously, if you want to keep the result, assign it to another variable:
PS> $y = $x.Replace($search, $replace)
The built-in -replace operator allows you to use a regex for this e.g.:
C:\PS> '-content-' -replace '-([^-]+)-', '&$1&'
&content&
Note the use of single quotes is essential on the replacement string so PowerShell doesn't interpret the $1 capture group.