How do I check if the user input is an integer and greater than zero and maximum 10?
I need to make a script which asks for a number from 0 to 10. This will be the amount of times the user can enter a number.
So if he enters 3, he has to be asked 3 times which number he wants to enter. When he entered the last number, the average has to been shown of the given number, and then the script ends.
Like this?
while ( (1..10) -notcontains $g)
{
$g = read-host "How many numbers do you want to put in? (value from 1 to 10) "
}
$ar=#()
for ($i=0; $i -lt $g; $i++)
{
$ar += read-host "Enter value $($i+1)"
}
$averageArray = ($ar | Measure-Object -Average).average
write-host "Average is : $averageArray"
Related
I have an integer array like below and I wanted to count number of 1's in that array in powershell, Can anyone help me here please,
[array]$inputs = 81,11,101,1811,1981
$count = 0
foreach($input in $inputs)
{
Write-Host "Processing element $input"
$count += ($input -like "*1*" | Measure-Object).Count
}
Write-Host "Number of 1's in the given array is $count"
It gives me only 5 1's in that array but expected answer is 10. Any help would be appreciated
Starting with a side note:
Don't use $Input as a custom variable as it is a preserved automatic variable
For what you are trying:
You iterating trough an array and check whether each item (with will automatically type cast to a string) is -like a 1 preceded by any number of characters and succeeded by any number of characters which is either true or false (and not the total number of ones in the string).
Instead
You might want to use the Select-String cmdlet with the -AllMatches switch which counts all the matches:
[array]$inputs = 81,11,101,1811,1981
$count = 0
foreach($i in $inputs)
{
Write-Host "Processing element $input"
$count += ($i | Select-String 1 -AllMatches).Matches.Count
}
Write-Host "Number of 1's in the given array is $count"
In fact, thanks to the PowerShell member enumeration feature, you do not even have to iterate through each array item for this, and just simplify it to this:
[array]$inputs = 81,11,101,1811,1981
$count = ($Inputs | Select-String 1 -AllMatches).Matches.Count
Write-Host "Number of 1's in the given array is $count"
Number of 1's in the given array is 10
I solved the above issue with below script,
[string]$inputs = 81,11,101,1811,1981
$count = 0
foreach($i in $inputs.ToCharArray())
{
if($i -eq "1")
{$count++}
}
Write-Host "Number of 1's in the given array is $count"
This is how I modify my Powershell array:
ForEach ($userID in $usersList) {
$allUsers += [pscustomobject]#{ID=$usersCounterTable;UserID=$userID;Name=$userInfo.DisplayName;Ext=$userInfo.ipPhone;Cellphone=$userInfo.mobile;Enabled=$isEnabled;VDI=$computerType;Title=$userTitle;}
$usersCounter += 1
$usersCounterTable = "[$usersCounter]"
}
Later in the code, the table is displayed and I want the user to be able to type a number to open the value, the number actually being the array index/offset (minus 1). I cannot find out how to do this.
$userID is actually the user's selection, because they can also type another employee's code to search, or search for his name for instance. I want the user to be able to select the array index number.
if (($userID.length -gt 0) -and ($userID.length -lt 5)) {
$indexNumber = ($userID - 1)
[????] $userFinalChoice = $allUsers[$userID].Name # NOT VALID
}
Above code works, if the user enter a number between 1 and 9999...
And then I would like to do this: $allUsers[$userID] ($userID being the number the user selected with Read-Host). Only, $allUsers[$userID].Name is not valid, but $allUsers[1].Name is. If I can figure this out, I'll be able to fix the rest of it and search for the return value.
Also need to make sure user doesn't input an index that is out of bounds of $usersList (Using $ErrorActionPreference = "SilentlyContinue" would probably work as it just reject the search reject but it's not that clean.)
From what I understand, I'm actually looking for the reverse of $usersList.IndexOf(‘David’), I want to provide the index and get returned the name.
Much appreciated - Powershell beginner.
The first code block you show us is really confusing, since you seem to grab user details from just... somewhere, so there is no telling if this info indeed belongs to the same user or not.
Also, I don't really think it is a good idea to use a formatted table as selection menu, especialy if the list gets large. Maybe you should think of building a form with a listbox or use the Out-GridView for this as Lee_Dailey suggested.
Anyway, if you want it as console menu, first make sure the ID number (really the index to select) starts with 1
$usersCounter = 1
# collect an array of PsCustomObjects in variable $allUsers
$allUsers = foreach ($userID in $usersList) {
# don't use $allUsers += , simply output the object
[PsCustomObject]#{
ID = "[$usersCounter]"
UserID = $userID
Name = $userInfo.DisplayName
Ext = $userInfo.ipPhone
Cellphone = $userInfo.mobile
Enabled = $isEnabled
VDI = $computerType
Title = $userTitle
}
$usersCounter++ # increment the counter
}
Next, show this as table so folks can select one of the users by typing the number displayed in the 'ID' column.
Do this in a loop, so when someone types anything else than a valid number, the menu is displayed again.
# start an endless loop
while ($true) {
Clear-Host
$allUsers | Format-Table -AutoSize
$userID = Read-Host "Enter the [ID] number to select a user. Type 0 or Q to quit"
if ($userID -eq '0' -or $userID -eq 'Q') { break } # exit from the loop, user quits
# test if the input is numeric and is in range
$badInput = $true
if ($userID -notmatch '\D') { # if the input does not contain an non-digit
$index = [int]$userID - 1
if ($index -ge 0 -and $index -lt $allUsers.Count) {
$badInput = $false
# everything OK, you now have the index to do something with the selected user
# for demo, just write confirmation to the console and exit the loop
Clear-Host
Write-Host "You have selected $($allUsers[$index].Name)" -ForegroundColor Green
break
}
}
# if you received bad input, show a message, wait a couple
# of seconds so the message can be read and start over
if ($badInput) {
Write-Host "Bad input received. Please type only a valid number from the [ID] column." -ForegroundColor Red
Start-Sleep -Seconds 4
}
}
I am trying to figure out how to do the following.
Read a text file with phone numbers in a list that are available each number on a separate line.
Output the available list to the script user to be able to select the best one.
Input the $number into another command to add it to the new user.
I have the following so far
$numbers = gc 'C:\temp\file.txt'
I can output the data by using $numbers[1], $numbers[2], etc., but how can I output this to look good and allow the user to select the best number with all options in the text file? I can do it manually obviously, but if I do 3 x $numbers[1], $numbers[2], $numbers[3] it will miss the numbers 4, 5, 6 etc.
try Something like this :
$selected=Get-Content "c:\temp\phone.txt" | Out-Gridview -Title "Select your choice" -OutputMode Single
if ($selected)
{
Write-Host "your choice is $selected"
}
Something like this:
$numbers = Get-Content 'C:\temp\file.txt'
$i = 1
foreach($n in $numbers){
Write-host "Number $i - $n"
$i++
}
$n = Read-host "Choose a number"
$chosenNumber = $number[$n-1]
How can I input multiple values in PowerShell and have those values stored in a variable?
For example:
$value = Read-Host "Enter the value's" #I need 15 values to be entered.
And then recall them e.g:
$value[0] = 1233
$value[1] = 2345
To do this you could declare an array #() and then use a loop and the addition operator to add items to the array (stopping when a blank value is submitted):
$values = #()
Do{
$value = read-host "Enter a value"
if ($value) {$values += $value}
}Until (-not $value)
You can then retrieve values as you described via the index with square brackets []:
$values #returns all values
$values[3] #returns the fourth value (if you entered four or more)
Beware that arrays start from 0, so the first item is [0], second is [1] etc. With PowerShell you can also use negative numbers to work through the array backwards, so [-1] is the last item, [-2] the second to last, etc.
Stores the readin values in an array:
$values = #()
$i = $null
while ($i -ne "q") {
if ($i -ne $null) {
# Attach value to array
$values += $i
}
$i = Read-Host "Enter value (stop with q)"
}
# Print each value in a seperate line
$values | % { Write-Host $_}
# Print type -> to visualize that it is an array
$values.GetType()
# Several values can be retrieved via index operator
$values[0]
I am new to power shell. I am trying to use the function like the goto in batch files.
In my script where I have$input1 = Read-Host "Please select an option 1, 2, 3. "
I want to Clear-Host and restart script if the use does not enter 1, 2, 3.
Write-Host 1. Convert Byte to Megabyte.
Write-Host
Write-Host 2. Convert Byte to Gigabyte.
Write-Host
Write-Host 3. Conver Byte to Terabyte.
#
#
# Assign value to the variables
#
$b2MB = '1048576'
$b2GB = '1073741824'
$b2TB = '1099511627776'
$input1 = ""
#
#
# prompts user for input from the main screen.
#
$input1 = Read-Host "Please select an option 1, 2, 3. "
#
#
# Depending on what the user input will execute a certain conversion.
#
#
if ( $input1 -eq 1 ) {
$mb2 = Read-Host " Enter how many bytes you want to convert to Megabytes? "
$bytesToMb = $mb2 / $b2MB
Write-Host $mb2 'is equal to '$bytesToMb' Megabytes'
} elseif ($input1 -eq 2) {
$mb3 = Read-Host " Enter how many bytes you want to convert to Gigabytes? "
$bytesToGb = $mb3 / $b2GB
Write-Host $mb3 'is equal to '$bytesToGb' Gigabytes'
} elseif ( $input1 -eq 3) {
$mb4 = Read-Host " Enter how many bytes you want to convert to Terabytes? "
$bytesToTb = $mb4 / $b2TB
Write-Host $mb4 'is equal to '$bytesToTb' Terabytes'
} else {
Write-Host " You have entered an invalid option. "
}
I believe you want something like this:
# Start a continuous loop
while ($true) {
# Write messages
Write-Host 1. Convert Byte to Megabyte.
Write-Host
Write-Host 2. Convert Byte to Gigabyte.
Write-Host
Write-Host 3. Conver Byte to Terabyte.
# Get the input
$input1 = Read-Host "Please select an option 1, 2, 3. "
# See if the input equals 1, 2, or 3. If so, break the loop.
if (1..3 -contains $input1) { break }
# If we get here, then the input was bad.
# So, we clear the host and let the loop start-over
Clear-Host
}
#
#
# Assign value to the variables
#
$b2MB = '1048576'
$b2GB = '1073741824'
$b2TB = '1099511627776'
#
#
# Depending on what the user input will execute a certain conversion.
#
#
if ( $input1 -eq 1) {
$mb2 = Read-Host " Enter how many bytes you want to convert to Megabytes? "
$bytesToMb = $mb2 / $b2MB
Write-Host $mb2 'is equal to '$bytesToMb' Megabytes'
} elseif ($input1 -eq 2) {
$mb3 = Read-Host " Enter how many bytes you want to convert to Gigabytes? "
$bytesToGb = $mb3 / $b2GB
Write-Host $mb3 'is equal to '$bytesToGb' Gigabytes'
} elseif ( $input1 -eq 3) {
$mb4 = Read-Host " Enter how many bytes you want to convert to Terabytes? "
$bytesToTb = $mb4 / $b2TB
Write-Host $mb4 'is equal to '$bytesToTb' Terabytes'
} else {
Write-Host " You have entered an invalid option. "
}
Easy enough, use a Do/Until loop.
#
#
# Assign value to the variables
#
$input1 = ""
# Start the loop to get the user's choice (with validation)
Do{
cls
Write-Host 1. Convert Byte to Megabyte.
Write-Host
Write-Host 2. Convert Byte to Gigabyte.
Write-Host
Write-Host 3. Conver Byte to Terabyte.
#
#
# prompts user for input from the main screen.
#
$input1 = Read-Host "Please select an option 1, 2, 3. "
}Until(#(1,2,3) -contains $input1)
Switch($input1){
1 {Read-Host "Enter how many bytes you want to convert to Megabytes? "|%{$Out = "{0:N} bytes is equal to {1:n4} Megabytes" -f [double]$_,($_/1MB);Write-Host "$Out"}}
2 {Read-Host "Enter how many bytes you want to convert to Gigabytes? "|%{$Out = "{0:N} bytes is equal to {1:n4} Gigabytes" -f [double]$_,($_/1GB);Write-Host "$Out"}}
3 {Read-Host "Enter how many bytes you want to convert to Terabytes? "|%{$Out = "{0:N} bytes is equal to {1:n4} Terabytes" -f [double]$_,($_/1TB);Write-Host "$Out"}}
}
I also used a Switch instead of a bunch of If/Then statements, and did the math with ###/1MB or /1GB or /1TB since Powershell can do that calculation for you.
Edit: Oh yeah, I also formatted the numbers. Adding commas makes it easier to read large numbers, and I truncated the calculated value to 4 places past the decimal. That can be changed by altering the 4 in {1:n4} to whatever you want the decimal to go to, or remove the 4 to include everything. If you make it a large decimal it will fill with zeros if that many do not exist. Such as 4.23 when formatted through {1:n5} comes out as 4.23000 since it has to have 5 places past the decimal.
Ok, the Switch loop is used instead of nested if statements like you were using. The syntax is
Switch(array to parse) {
Value or scriptblock {action to perform on match}
Different value or scriptblock {action to perform on match}
}
So in your case there is only one thing that we are parsing, and that is the users selection. So let's say they choose 2 to convert to Gigabytes. $input2 = 2. Switch starts comparisons at the top, and checks if the value is 1. It is not so it moves to the next line. It checks to see if the value is 2. It is, so the switch command performs the actions in the accompanying scriptblock there. We will get to that in a moment. After it finished that scriptblock it moves to the next line and checks if the value is 3. It is not, and that was the last option so it finishes that loop. There is not another value to parse since $input2 only had one value so it exits the switch loop. Switch works on arrays so there could have potentially have been more things to compare against the three options in the switch loop.
That is the switch loop. Let's look at the scriptblock that it ran when the value matched up for the second option. I'll break it down a bit here...
Read-Host "Enter how many bytes you want to convert to Gigabytes? "|
%{
$Out = "{0:N} bytes is equal to {1:n4} Gigabytes" -f [double]$_,($_/1GB);
Write-Host "$Out"
}
That first line is pretty much yours if I remember right, but instead of storing the value in a variable for use later I pipe it to a for each loop (%{...} is short for foreach{...}). Then, since write-host doesn't really allow formatting I do some formatting and save the string in $out. So this is where it might get intimidating. "{0:N}" works with the -f which is short for -format. It works like a place holder that says to look at the -f command at the end of the string and get the first thing provided to it (arrays in powershell start at record 0, so usually a reference to item 0 is looking for the first item). Once it gets that first value that follows the -f it applies the formatting specified after the colon N which means it formats it like a number putting a comma every three digits.
Ok, there is some text in there and then {1:N4} which is another formatting placeholder. The part before the colon specifies which item to fetch, and since 0 was the first value to be formatted, 1 must be the second. So it gets the second value and applies the formatting after the colon. N4 again says it is a number, but specifies to only show the first 4 numbers past the decimal.
Then it has the -f which says that there are some things to format. The first item is $_ which is the value that the user entered which was piped into the foreach loop. The [double] before it specifies the type of object it is. Double is a kind of number, like int32 or hex, but it has very loose guidelines so the user can enter very large values and not have issues. That gets passed directly to the first placeholder. Then comes $_/1GB which is the number that the user entered divided by Gigabytes, because powershell has that ability built in. It finds the result of that and passes it to the second placeholder. So now we have the text that we want to pass back to the user, with the numbers nicely formatted and easy to read, and stored that string into $out. Last thing in that scriptblock is to write $out to the host.
Now you may ask why I had to specify that $_ as a [double] the first time, but not the second. The reason is that the second time I was performing math on it, so powershell figures that it must be a number if I'm dividing it, so I don't have to declare it there.
I hope that makes the script make more sense now.