I am new to powershell scripting. I am supposed to check to see if the first parameter passed is a string and second parameter is an int.
function positions {
param (
[string] $inputstring,
[int] $num )
}
$inputstring=read-host "Enter your name"
if ( !$inputstring -eq "" ) {
Write-Output "The first recieved parameter is: " $inputstring "and its type is a string"}
else { Write-Output "The first received parameter is:" $inputstring "and its type is not a string" }
$num=read-Host "Enter a number"
if ( $num -eq int ) {
Write-Output "This second parameter is" $num "and its type is a integer"}
else { Write-Output "This second parameter is" $num "and its type is not a integer"}
I believe the if statement for the string is wrong because it give me right input only if i negate it with '!'
Also, for the int, if statement it is not reading 'int' after -eq.
I am extremely new to this so need help.
Firstly, when you take input from screen using read-host the input will be read and stored as a string, irrespective of what you enter. You can confirm this by running the following command and entering a number:
($checkInt = read-host).GetType().Name
This will output string, no matter what you enter. The equivalent would be to define the input variable like this:
$checkInt = "10"
$StringVariable = "This is a string"
$IntVariable = 10
$StringIntVariable = "10"
## Print out variable types
"String variable is type " + $StringVariable.GetType().Name
"Int variable is type " + $IntVariable.GetType().Name
"StringInt variable is type " + $StringIntVariable.GetType().Name
Which again, if you check the type of that variable will return string.
What you need to do is cast to an int and check if the value is null or check if the value is numeric:
## Checking if user input is alphanumeric
$stringIntVariable = Read-Host "Enter a number"
if (($stringIntVariable -as [int]) -ne $null) {
"StringIntVariable is numeric"
}
else {
"StringIntVariable is not numeric"
}
With regards to your code, the below will work how you want it to:
$inputstring = read-host "Enter your name"
if (($inputstring -as [int]) -eq $null) { ## Check if not castable to int
Write-Output "The first recieved parameter is: " $inputstring "and its type is a string"
}
else {
Write-Output "The first received parameter is:" $inputstring "and its type is not a string"
}
$num=read-Host "Enter a number"
## Checking if user input is numeric
if (($num -as [int]) -ne $null) {
Write-Output "This second parameter is" $num "and its type is a integer"
}
else {
Write-Output "This second parameter is" $num "and its type is not a integer"
}
As #TheMadTechnician pointed out using ($num -as [int]) -ne $null is more forgiving than using a regex match.
You can use GetType().
When checking for type equality put square brackets around the type ([string]):
if ( $inputstring.GetType() -eq [string] )
{
# $inputstring is type String
}
else
{
...
}
The value coming from Read-Host will always be a string, so one option to verify $num is an int is to cast it to an int. However, this will throw an exception if the input is not actually an integer, so instead of if else you could use try catch block:
$num = read-Host "Enter a number"
try {
# cast to int
$num = [int]$num
# $num is type int (Int32)
}
catch
{
# $num is not an int
}
Related
See code below
##If user inputs %100 or a100 or non-numeric value for temp, I need to display "Error: You must enter a numeric Value!" Write-host $("Error: You must enter a numeric Value!")
## then goes back to start
##im guessing if ($value isnot [int]) or something like that for it to work. thank you.
##Error I get without proper coding......What is the temperature in Fahrenheit: a111
##Cannot convert value "a111" to type "System. Single". Error: "Input string was not in a ##correct format."
Write-Host("="*31)
Write-Host $("Fahrenheit to Celsius Converter")
Write-Host $("Script Written By Jesse ")
Write-Host("="*31)
$value = (Read-Host("What is the temperature in Fahrenheit"))
$fahr = (($value -32) /9) *5
Write-Host $("Fahrenheit", $value, "is equal to Celsius:", [Math]::Round($fahr,3))
$input = (Read-Host("Do you want to convert another Fahrenheit value? (1 = yes, 0 = no)?"))
Write-Host ("="*31)
while ($input)
{
if ($input -eq 1)
{
Write-Host $("Fahrenheit to Celsius Converter")
Write-Host $("Script Written By Jesse Nieto ")
Write-Host ("="*31)
$value = (Read-Host("What is the temperature in Fahrenheit"))
$fahr = (($value -32) /9) *5
Write-Host $("Fahrenheit", $value ,"is equal to Celsius:" ,[Math]::Round($fahr,3))
$input = (Read-Host("Do you want to convert another Fahrenheit value? (1 = yes, 0 = no)?"))
Write-Host("="*31)
}
elseif ($input -eq 0)
{
Write-Host $("Thank You. Bye! ")
break
}
else
{
Write-Host $("Please enter a valid option! ")
$input = (Read-Host ("Do you want to convert another Fahrenheit value? (1 = yes, 0 = no)?"))
Write-Host ("="*31)
}
}
There is much redundant code on your script which could be simplified, the biggest issue is the use of $input which is an automatic variable and should not be assigned manually. As for the formula to convert from Fahrenheit to Celsius, you could use a function for that, as aside, according to Google, the formula should be (X − 32) × 5 / 9 though I'm not an expert on this, feel free to change for whatever you like.
function ConvertTo-Celsius {
param([int]$Value)
($value - 32) * 5 / 9
}
:outer while($true) {
$value = Read-Host "What is the temperature in Fahrenheit"
try {
$celsius = ConvertTo-Celsius $value
}
catch {
# If input was invalid restart the loop
Write-Host "Invalid input, only integers allowed!"
continue
}
Write-Host "Fahrenheit $value°F is equal to $([math]::Round($celsius, 3))°C"
do {
$shouldExit = Read-Host "Do you want to convert another Fahrenheit value? (1 = yes, 0 = no)?"
switch($shouldExit) {
0 {
Write-Host "Thank You. Bye!"
break outer
}
1 { continue }
Default { Write-Host "Please enter a valid option!" }
}
} until($shouldExit -eq 1)
}
I have this piece of code in PowerShell. I need user input validation to integer with writing output saying what is wrong with the input and expecting correct input.
$FromObj = "Please input object number"
$FromInput = Read-Host $FromObj
while(($FromInput -isnot [int])) {
#I also want to put in the while that the input has to be an integer, -gt 0, and -lt 800
Write-Output "Your input has to be a number."
$FromInput = Read-Host $FromObj
}
if ($FromInput -le 0) {
Write-Output "Your input has to be a number greater than 0!"
$FromInput = Read-Host $FromObj
}
elseif ($FromInput -ge 800) {
Write-Output "Your input has to be a number less than 800!"
$FromInput = Read-Host $FromObj
}
else {
$FromInput = $FromInput -as [int]
}
However, this is not working for me. Could you help me with validating it with writing outputs as the ones displayed above?
I think Nicks's link in comment already provides different right answers to your question i.e.: using regex to match \d+ (digits) or using [int]::TryParse(...) but to explain why your code is not working:
Read-Host will store user input as string unless you manipulate it which is what you were already doing on your last condition (the else {...} statement).
This is why you never get past the $FromInput -isnot [int] condition.
To fix the code you could simply attempt to store user input -as [int] since the beginning and since you have 3 Read-Host on your code you could save the user input attempt -as [int] in a ScriptBlock which then can be easily executed as many times as needed:
$FromObj = "Please input object number"
$giveMeNumber = { (Read-Host $FromObj) -as [int] }
$FromInput = & $giveMeNumber
while($FromInput -isnot [int]) {
Write-Output "Your input has to be a number."
$FromInput = & $giveMeNumber
}
if ($FromInput -le 0) {
Write-Output "Your input has to be a number greater than 0!"
$FromInput = & $giveMeNumber
}
elseif ($FromInput -ge 800) {
Write-Output "Your input has to be a number less than 800!"
$FromInput = & $giveMeNumber
}
Note, even though this works, the statement is not entirely correct since you're breaking out of the while loop after the input is [int] the user could force an incorrect input.
Try this instead which will execute indefinitely until right input:
Clear-Host
$ErrorActionPreference = 'Stop'
$FromObj = "Please input object number"
$scriptBlock = {
try
{
$FromInput = [int](Read-Host $FromObj)
# Note I'm using Write-Host instead of Write-Ouput, this is because
# we don't want to store the invalid inputs messages in the
# $userInput variable.
if ($FromInput -le 0) {
Write-Host "Your input has to be a number greater than 0!"
& $scriptBlock
}
elseif ($FromInput -ge 800) {
Write-Host "Your input has to be a number less than 800!"
& $scriptBlock
}
else {
$FromInput
}
}
catch
{
Write-Host "Your input has to be a number."
& $scriptBlock
}
}
$userInput = & $scriptBlock
I don't understand why pressing enter key is the same as pressing 0 on the keyboard.
[int] $Choice = -1
$Count = 2
while ($Choice -lt 0 -or $Choice -gt $Count)
{
Write-Host "Input number"
$Choice = Read-Host
Write-Host "choice:"
Write-Host $Choice
}
The output will be 0 even if just press enter. I want the user to explicitly input 0.
In the very first statement:
[int] $Choice = -1
... you type-cast $choice to [int].
When you apply a cast to the left-hand side of an assignment (to the left of the variable name), PowerShell will "remember" it as a type-constraint and treat the variable as strongly typed - PowerShell will attempt to convert anything you assign to $choice from there on out to an [int].
Hitting enter in the prompt without any other input results in Read-Host returning an empty string (like "")
The conversion logic treats the empty string as $null, and casting $null to [int] results in the value 0. You can see this by casting an empty string to [int] directly:
PS C:\> [int]""
0
You should probably validate the input from Read-Host before assigning to $Choice if you explicitly require a number:
$inputString = Read-Host
if($inputString -notmatch '^\d+$') {
Write-Host "Digits only please!"
continue
}
What exactly am I doing wrong here, it seems to be subtracting just fine but adding and multiplying seems to not work at all.
How do I get it to do the calculations correct and allow the if statement to also work as it seems to always run even if the numbers are incorrect size.
$a = Read-Host "What is your name?"
$b = Read-Host "Enter a 2 digit number"
$c = Read-Host "Enter a 3 digit number"
if (($b -ge 10) -and ($b -le 99) -and ($c -ge 100) -and ($c -le 999)){
$d = $b + $c
$e = $b * $c
$g = $b - $c
$d
$e
$g
Write-host "Here you go $a"
}
else {
write-host "Enter the numbers correctly"
}
Here the results I get
Read-Host always outputs a string.
In order to treat the output as a number, you must explicitly convert it to one:
$a = Read-Host "What is your name?"
# Note: Add error handling with try / catch
# and a retry loop to deal with invalid input.
[int] $b = Read-Host "Enter a 2 digit number"
[int] $c = Read-Host "Enter a 3 digit number"
The above type-constrains variables $b and $c to integer values (by placing the [int] cast to the left of the target variable in the assignment), which automatically converts Read-Host's [string] output to [int].
To spell it out with a concrete example that prompts until a two-digit (decimal) number is entered:
do {
try {
[int] $b = Read-Host "Enter a 2 digit number"
} catch {
continue # Not a number - stay in the loop to prompt again.
}
if ($b -ge 10 -and $b -le 99) { break } # OK, exit the loop.
} while ($true)
Note: Strictly speaking, the [int] cast accepts anything that would work as a number literal in PowerShell, which includes hexadecimal representations, such as 0xA, as well as number with a type suffix, such as 10l - see this answer for more information.
As for what you tried:
Except for -, all the operators used in your code have string-specific overloads (meaning); note that it is sufficient for the LHS to be of type [string] to trigger this behavior.[1]
-lt / -ge perform lexical comparison with strings; e.g., '10' -gt '2' yields $false, because, in lexical sorting, string '10' comes before string '2'.
-and / -or treat empty strings as $false, and any nonempty string as $true; e.g., '0' -and '0' is $true, because '0' is a nonempty string.
+ performs string concatenation; e.g., '1' + '0' is '10'.
* performs string replication; e.g., '1' * 3 is '111' - the LHS is repeated as many times as specified by the number on the RHS; note that '1' * '3' works the same, because the RHS is coerced to an [int] in this case.
- is the only exception: it always performs a numeric operation, if possible; e.g, '10' - '2' yields 8, because both operands were implicitly converted to [int]s.
[1] Typically, it is the LHS of an operation that determines its data type, causing the RHS to be coerced to a matching type, if necessary.
This should be really simple, but I cannot make it work. I'm new to the PowerShell so my mistake is probably obvious. I'm trying to ask a user for an input using a while loop, and prompting the user to try again if what was entered was not numeric. In bash it would look like this:
while read -p "What is the first number? " first; do
if [[ $first = *[[:digit:]]* ]]; then
break # if $first is numeric, break loop
else
echo "$first is not numeric. Enter a numeric value. "
fi
done
Here's what I have for the PS:
While ($first = (Read-Host "What is the first number?") -as [double]) {
if ($first -eq $null) { Write-Host "Please enter a numeric value." }
else { break }
}
In the example above, I can break the loop fine when a number is entered, but I can't see the Write-Host statement if I type a string.
Looking at the While line:
While ($first = (Read-Host "What is the first number?") -as [double])
This will only enter/continue the loop body when the input is already a double, because it rolls up the cast to double as part of the loop condition. You want to enter the loop body on any input, and only check if it's a double afterwards. At least, that's what the bash code does:
While ($first = (Read-Host "What is the first number?")) {
if ( ($first -as [double]) -eq $null) { Write-Host "Please enter a numeric value." }
else { break }
}
Or you could continue using the cast as part of the condition by negating the whole expression, and thus avoid the need for the awkward break:
While (-not ($first = (Read-Host "What is the first number?") -as [double])) {
Write-Host "Please enter a numeric value."
}
You could use this to keep prompting for a valid number input as you are looking for.
Do {
"Please enter a numeric value." | Out-Host
$first = (Read-Host "What is the first number?") -as [double]
} While($null -eq $first)