powershell "if" needs to set two variables on match - powershell

I need to set two variables in a script...
The first is obviously $vmcluster - What's the proper syntax to set another variable if my "if" matches?
if ($vmname -like "LouPr*") {$vmcluster = "Production"}

It's a script-block.... just use another line, or seperate with ; .
if ($vmname -like "LouPr*") {
$vmcluster = "Production"
$secondvar = "secondvalue"
}
or
if ($vmname -like "LouPr*") { $vmcluster = "Production"; $secondvar = "secondvalue" }

Related

powershell regex replace using variable parameters when calling replace

I wondering how to make the following powershell code work with regular expressions. For example I want to call it like this:
rename_file -OneFile proj1_file.txt -Replace0 "^proj1_" -Replace1 "mynewproj_"
The problem is that as soon as I add the regular expression caret (^) my function stops matching for the replace function... If I remove the caret anchor the code works... but is dangerous because its not anchored to the front of the string... I really want the regular expressions chracters to work when passing the string in to this function...
Here's my powershell code...
$script:TotalRename = 0
function rename_file {
param(
[string]$OneFile,
[string]$Replace0,
[string]$Replace1
)
#$NewName = $OneFile.Replace($Replace0, $Replace1)
$NewName = $OneFile -replace $Replace0, $Replace1
if ($NewName -eq $OneFile) {
write-host "NoChange $OneFile"
return
}
$script:TotalRename = $script:TotalRename + 1
write-host "rename $OneFile => $NewName"
}

PowerShell String Array Pattern Matching

I have a PowerShell query.
I have the below 2 string arrays. What I want to be able to do is to return only those entries from $RecycleBinPaths that do not begin with all the entries from $ExcludeRecycleBinsPathWildCards (i.e. Wildcard pattern match)
$RecycleBinPaths = #('C:\$Recycle.Bin','D:\$RECYCLE.BIN','E:\$RECYCLE.BIN','F:\$RECYCLE.BIN','L:\$RECYCLE.BIN','M:\$RECYCLE.BIN','S:\$RECYCLE.BIN','T:\$RECYCLE.BIN')
$ExcludeRecycleBinsPathWildCards = #('C:\','F:\')
In the above example I want the output to be:
D:\$RECYCLE.BIN
E:\$RECYCLE.BIN
L:\$RECYCLE.BIN
M:\$RECYCLE.BIN
S:\$RECYCLE.BIN
T:\$RECYCLE.BIN
In fact $ExcludeRecycleBinsPathWildCards array above can contain any number of entries, not necessarily just 2 as shown above.
Are you able to help? Thanks.
Use nested .Where() methods:
$RecycleBinPaths.Where({
# Save path to separate variable
$path = $_
# Now test if _any_ string in the list of wildcards match, and then apply -not - making it resolve to true only if _none_ of the wildcards match the path
-not $ExcludeRecycleBinsPathWildCards.Where({ $path -like "$_*" }, 'First')
})
Another way of looping through the items and adding to another array.
$RecycleBinPaths = #('C:\$Recycle.Bin','D:\$RECYCLE.BIN','E:\$RECYCLE.BIN','F:\$RECYCLE.BIN','L:\$RECYCLE.BIN','M:\$RECYCLE.BIN','S:\$RECYCLE.BIN','T:\$RECYCLE.BIN')
$ExcludeRecycleBinsPathWildCards = #('C:\','F:\')
$SelectedRecycleBinPaths = #()
foreach($rbp in $RecycleBinPaths)
{
if(-Not ($ExcludeRecycleBinsPathWildCards -contains $rbp.ToString().Substring(0,3)))
{
$SelectedRecycleBinPaths += $rbp
}
}
$SelectedRecycleBinPaths
D:\$RECYCLE.BIN
E:\$RECYCLE.BIN
L:\$RECYCLE.BIN
M:\$RECYCLE.BIN
S:\$RECYCLE.BIN
T:\$RECYCLE.BIN

I am trying to convert the "Return First recurring character in a string problem" from python to powershell

I have completed coding this same problem in python and was trying to generate a similar logic or atleast achieve a similar result in powershell.
Python Code-
def FRC(str):
h = {}
for ch in str:
if ch in h:
return ch
else:
h[ch] = 0
return '\0'
print(FRC("abcdedcba"))
I have tried a few possible codes and was able to only enumerate the array of characters to count their occurrences. Thank you for any suggestions.
Update1 - The code I have worked on is as follows:
function get-duplicatechar {
[CmdletBinding()]
param (
[string]$teststring
)
$hash = #()
$teststring = $teststring.ToCharArray()
foreach ($letter in $teststring)
{
if($letter -contains $hash){
return $letter
}else {
$hash = $hash + $letter
}
return "\0"
}
}
get-duplicatechar("saahsahh")
You could use the (.Net) HashSet class for this, which Add method (besides adding the value,) returns true if the element is added to the HashSet<T> object and false if the element is already present.
function get-duplicatechar {
[CmdletBinding()]
param (
[string]$str
)
$h = [System.Collections.Generic.HashSet[char]]::new()
foreach ($ch in $str.ToCharArray()) {
if(!$h.add($ch)) { return $ch }
}
}
Here's a working version using your code as base:
function get-duplicatechar {
[CmdletBinding()]
param (
[string]$teststring
)
$hash = #{}
$CharArray = $teststring.ToCharArray()
foreach ($letter in $CharArray) {
if($letter -in $hash.Keys) {
$letter
break
}
else {
$hash[$letter] = $null
}
}
}
One problem is that you are strongly typing $teststring to be a string, so when you add a character array later PowerShell just converts it into a string and thus $teststring remains a string (try $teststring.GetType() after $teststring = $teststring.ToCharArray() to see this for yourself).
One way to solve this is to do what I did and use a different variable for the character array. You could also solve it by changing the variable to a character array directly by replacing [string]$teststring with [char[]]$teststring, that way any strings input to the function will be automatically cast as a character array.
The next mistake is using -contains where you need -in. The letter doesn't contain the array, you're looking for the letter in the array, just like you did in Python.
You can drop the return keyword entirely, PowerShell does not need it. Any output in your function will be output from the function automatically.
You also call your collection variable "hash", but you made an array. I changed it to be an actual hashtable, just like in your Python code. I also changed the way we add to it to more closely reflect what you did in Python. There are many ways to do this, this is just one. Notice we'll need to add ".Keys" in our if-statement as well so we check for keys matching our letter.
I think that's it, ask if anything is unclear.

If statement - Four variables, only run if one true

I have the following which doesn't allow both variables to be enabled (boolean true value):
If (($Variable1) -and ($Variable2)) {
Write-Warning "Both variables have been enabled. Modify script to enable just one."
Pause
Break
}
This works great, however, how would I ensure only one is ever enabled when 4 possible variables exist? I'm thinking a combination of -and & -or?
You can add the boolean values and check their count:
If (([bool]$Variable1 + [bool]$Variable2 + [bool]$Variable3) -ne 1) {
...
}
but of course you have to make sure that these can actually be cast to boolean.
That's what "exclusive or" (xor) is for:
If ($Variable1 -xor $Variable2 -xor $Variable3) {
....
}
About logical operators in Powershell
Cannot think of a way to do this that avoids using a counter. You have to check the value of each variable and keep count of how many are $true.
$trueCount = 0
($variable1, $variable2, $variable3, $variable4) | % { if ($_ ) { $trueCount++} }
if ($trueCount -eq 1) {
write-host "only one variable true"
}
else {
write-host "condition not met"
}

Writing a hashtable value to an attribute

Powershell newbie here, my first script.
I have user objects with an AD custom attribute named tvCode with a values of 123456 or 6787682 or 983736 etc.
I would like to script something that will get the tvCode value from the user object
When:
123456 = Sony
6787682 = Samsung
9837343 = LG
Write the value of "Sony" or "Samsung" or "LG" to the "City" attribute of the user object.
Looks like i may need to use a hashtable.
If possible do this for a specific OU
hope this makes sense
thanks
function Convert-TVCode {
Param
(
[parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]
[String[]]
$Code
)
Process {
foreach ($C in $Code) {
switch ($C) {
"123456" {$brand = "Sony"}
"6787682" {$brand = "Samsung"}
"9837343" {$brand = "LG"}
default {
$brand = $null
Write-Warning "$C not included in switch statement. Returning"
return
}
}
if ($brand) {
Write-Verbose "Code '$C' matched to Brand '$brand' -- searching for users to update"
Get-ADUser -Filter "tvCode -eq '$C'" | Set-ADUser -Replace #{tvCode=$brand}
}
}
}
}
This function will allow you to update any users that have their tvCode attribute set as one of the target numerical values. You can have it hit multiple codes at once as well.
Examples:
Convert-TVCode -Code 123456
Convert-TVCode -Code 123456,6787682
Convert-TVCode -Code 123456,6787682,9837343 -Verbose
Update the switch statement in the function to customize it to your actual values and let me know if you have any questions!